Docker Composeని boot సమయంలో auto-start చేయడం ఎలా
reboot తర్వాత Docker Compose సేవలు ఎందుకు తిరిగి రావో తెలుసుకోండి: restart policies, on-failure ఒక్కసారి ఎందుకు పనిచేయదో, systemd unit ఎప్పుడు అవసరమో చూడండి.
సంక్షిప్త సమాధానం
రెండు షరతులు ఒకేసారి నెరవేరితే Docker Compose సేవలు boot సమయంలో ప్రారంభమవుతాయి. Docker daemon system serviceగా enabled అయి ఉండాలి. అలాగే fileలోని ప్రతి serviceకు unless-stopped లేదా always restart policy ఉండాలి. ప్రతి serviceకు restart: unless-stopped జోడించి, docker compose up -d ను ఒక్కసారి అమలు చేయండి. Reboot తర్వాత containers స్వయంగా మళ్లీ ప్రారంభమవుతాయి. సాధారణ సందర్భంలో ఇంతకంటే మరేమీ అవసరం లేదు.
క్రమం ముఖ్యమైనప్పుడు మాత్రమే systemd unit అవసరం. ఉదాహరణకు, mounted disk, VPN interface లేదా Docker daemon ప్రారంభమయ్యే సమయానికి సిద్ధంగా లేని network shareపై ఆధారపడే stack ఉన్నప్పుడు ఇది అవసరం. ఆ సందర్భం వాస్తవమే. ఈ guide రెండో భాగం దానిని వివరిస్తుంది. Service definitions మరియు volumesపై మీకు ఇంకా అవగాహన అవసరమైతే, ముందుగా VPSలో Docker Compose ప్రాథమిక అంశాలు ప్రారంభించి, తర్వాత తిరిగి రండి.
compose.yaml లో restart policy ని సెట్ చేయడం
ప్రతి service కు policy ఒక లైన్గా ఉంటుంది. Global switch లేదు. అందువల్ల మీరు మర్చిపోయిన service reboot తర్వాత ఆగిపోయి ఉంటుంది, మిగతా stack మాత్రం ప్రారంభమవుతుంది.
services:
app:
image: nginx:1.27
restart: unless-stopped
ports:
- "8080:80"
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_PASSWORD: change-me
volumes:
- dbdata:/var/lib/postgresql/data
volumes:
dbdata:దాన్ని అమలు చేసి, నడుస్తున్న container నుంచి policy ని తిరిగి చదవండి:
docker compose up -d
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' $(docker compose ps -q app)ఇది unless-stopped ను ప్రదర్శిస్తుంది. no ప్రదర్శిస్తే, file సవరించబడింది కానీ container ను ఎప్పుడూ మళ్లీ సృష్టించలేదు.
ఇదే అత్యంత సాధారణ వైఫల్యం. Restart policy container లో నిల్వ ఉంటుంది, YAML file లో కాదు. ఇప్పటికే ఉన్న container కు compose.yaml ను సవరించడం వల్ల ఏ మార్పూ ఉండదు. docker compose restart కూడా సహాయపడదు, ఎందుకంటే అది అదే container object ను ఆపి మళ్లీ ప్రారంభిస్తుంది; దాని configuration ను మార్చదు. docker compose up -d మాత్రమే file ను నడుస్తున్న containers తో పోల్చి, policy మారిందని గుర్తించి, వాటిని మళ్లీ సృష్టిస్తుంది.
ప్రస్తుతం మళ్లీ సృష్టించకూడదనుకున్న container కోసం policy ని ఉన్నచోటే మార్చండి:
docker update --restart unless-stopped my-containerఅయినా YAML file ను కూడా సవరించండి. docker update నడుస్తున్న container ను మారుస్తుంది. తదుపరి docker compose up -d file ను చదివి పాత విలువను మళ్లీ అమలు చేస్తుంది.
ప్రతి restart విలువ వాస్తవంగా చేసే పని
Docker నాలుగు విలువలను నిర్వచిస్తుంది. వాటి మధ్య తేడా machine reboot అయినప్పుడు లేదా daemon restart అయినప్పుడు మాత్రమే కనిపిస్తుంది.
noడిఫాల్ట్. ఏ పరిస్థితిలోనూ container స్వయంచాలకంగా restart కాదు.alwayscontainer ఆగిన ప్రతిసారీ దాన్ని restart చేస్తుంది. మీరు దాన్ని చేతితో ఆపినా, Docker daemon తదుపరిసారి start అయినప్పుడు అది మళ్లీ ప్రారంభమవుతుంది. ఇది తరచుగా ఆశ్చర్యం కలిగిస్తుంది: గత వారం మీరు ఉద్దేశపూర్వకంగా ఆపిన container, reboot తర్వాత మళ్లీ running స్థితిలో ఉంటుంది.unless-stopped,alwaysవలే పనిచేస్తుంది. అయితే చేతితో ఆపిన container daemon restart అయిన తర్వాత కూడా ఆపిన స్థితిలోనే ఉంటుంది. నిర్వహణ కోసం అప్పుడప్పుడు serviceని నిలిపివేయాల్సి వస్తే, ఈ విలువను ఉపయోగించండి.on-failurecontainer non-zero exit codeతో exit అయినప్పుడు మాత్రమే దాన్ని restart చేస్తుంది.restart: on-failure:3వలే ప్రయత్నాల సంఖ్యకు పరిమితి విధించవచ్చు.
server upలో ఉన్నప్పుడల్లా stack కూడా upలో ఉండాలి అనుకుంటే, unless-stopped సరైన డిఫాల్ట్. container downలో ఉండకుండా నిరోధించాలనుకున్నప్పుడు మాత్రమే always ఎంచుకోండి.
ఎందుకు పునఃప్రారంభం కావడం లేదు: on-failure reboot తర్వాత కొనసాగదు
చాలా మంది on-failure ను జాగ్రత్తగా అనిపించడం వల్ల ఎంచుకుంటారు. కానీ మొదటి reboot తర్వాత ప్రతి container ఆగిపోయిందని గమనిస్తారు. కారణం దాని నిర్వచనంలోనే ఉంది. on-failure ఒక్క విషయానికే స్పందిస్తుంది: container process error code తో ముగియడం.
reboot అనేది error కాదు. host shutdown అయినప్పుడు, systemd docker.service ను ఆపుతుంది. daemon ప్రతి container ను ఉద్దేశపూర్వకంగా ఆపుతుంది. container విఫలం కాలేదు. అందువల్ల policy స్పందించాల్సిన పరిస్థితి ఉండదు. host తిరిగి ప్రారంభమైనప్పుడు, daemon తిరిగి ప్రారంభించాల్సిన containers ను పరిశీలిస్తుంది. శుభ్రంగా ఆపబడిన on-failure container వాటిలో ఉండదు. అది exited state లోనే ఉంటుంది.
దీనిని నేరుగా చూడవచ్చు. ఒక service పై restart: on-failure సెట్ చేయండి, docker compose up -d అమలు చేయండి, reboot చేయండి. తర్వాత ఈ command ను అమలు చేయండి:
docker compose ps -aఆ service Exited state తో, Exited (0) 2 minutes ago వంటి status తో జాబితా అవుతుంది. ఏదీ తప్పుగా లేదు. ఏదీ error గా log చేయబడదు. అందువల్ల సమస్యను గుర్తించడం కష్టం. policy తన నిర్వచనం ప్రకారమే పనిచేసింది.
on-failure ఇప్పటికీ ఉపయోగకరమే. job అమలు చేసే, కొన్నిసార్లు crash అయ్యే container కు ఇది సరిపోతుంది. పరిమిత సంఖ్యలో retries కావాలనుకున్నప్పుడు, restart loop వద్దనుకున్నప్పుడు దీనిని ఉపయోగించవచ్చు. reboot తర్వాత దీర్ఘకాలం నడిచే service ను సజీవంగా ఉంచడానికి ఇది సరైన సాధనం కాదు.
పునఃప్రారంభ విధానాలు పనిచేయాలంటే boot సమయంలో Docker service ప్రారంభం కావాలి
పునఃప్రారంభ విధానాలను Docker daemon అమలు చేస్తుంది. daemon ప్రారంభం కాకపోతే, ఏదీ అమలు కాదు. దీన్ని తనిఖీ చేయండి:
systemctl is-enabled docker
systemctl is-enabled containerdరెండూ enabled చూపాలి. Docker యొక్క అధికారిక repository నుంచి వచ్చే packages, install సమయంలో వీటిని enable చేస్తాయి. అందువల్ల కొత్త serverలో ఈ తనిఖీ సాధారణంగా విజయవంతమవుతుంది. ఏదైనా disabled చూపితే, దాన్ని సరిచేయండి:
sudo systemctl enable --now docker containerdఇక్కడ ఒక ముఖ్యమైన విషయం ఉంది. Ubuntuలో docker.socket కూడా అందుబాటులో ఉంటుంది. Docker APIతో ఏదైనా మొదటిసారి కమ్యూనికేట్ చేసినప్పుడు ఇది daemonను అవసరానికి అనుగుణంగా ప్రారంభిస్తుంది. docker.socket enabledగా ఉందని చూసి, daemon నియంత్రణలో ఉందని భావించి, memoryని ఆదా చేయడానికి docker.serviceను disable చేస్తారు. boot సమయంలో APIని పిలిచే ప్రక్రియ ఏదీ ఉండదు. అందువల్ల socketను ఎవరూ access చేయరు, daemon ప్రారంభం కాదు, మీరు మొదటి docker commandను టైప్ చేసే వరకు ఏ container కూడా ప్రారంభం కాదు. Socket activation అనేది docker.service enabledగా ఉండటానికి ప్రత్యామ్నాయం కాదు.
systemd unit సరైన పరిష్కారం అయ్యే సందర్భాలు
Restart విధానాలకు సిస్టమ్లోని ఇతర భాగాలతో క్రమాన్ని నిర్ణయించే సామర్థ్యం ఉండదు. Daemon ప్రారంభమవుతుంది. సాధ్యమైనంత త్వరగా అది మీ containersను ప్రారంభిస్తుంది. మీ stack ప్రత్యేక volume, NFS (network file system) share లేదా encrypted disk నుంచి directoryని bind-mount చేస్తే, ఆ path అందుబాటులోకి రాకముందే containers ప్రారంభం కావచ్చు. Docker mount point వద్ద ఖాళీ directoryని సృష్టించి, దానిపై containerను ప్రారంభిస్తుంది. ఫలితంగా మీ database ఎలాంటి data లేకుండా ప్రారంభమవుతుంది.
కింది పరిస్థితుల్లో ఏదైనా ఉంటే systemd unit రాయండి. Stack ప్రారంభం కావడానికి ముందు mount, VPN interface లేదా మరొక unit సిద్ధంగా ఉండాలి. ఈ hostలోని ఇతర servicesలా systemctl stop myapp మరియు systemctl start myapp పనిచేయాలి. లేదా shutdown సమయంలో daemonతో పాటు stackను బలవంతంగా ఆపకుండా, సక్రమంగా నిలిపివేయాలి. systemd units మీకు కొత్తైతే, systemd service మరియు timer రాయడం file formatను మరింత వివరంగా వివరిస్తుంది.
systemd యూనిట్ను రాయడం
Stackను home directory వెలుపల ఉన్న స్థిరమైన pathలో ఉంచండి. /srv/myapp మంచి ఎంపిక, ఎందుకంటే ఎవరూ login చేయకముందే నడిచే unitకు /home చదవాల్సిన అవసరం లేదు.
/etc/systemd/system/myapp.service ను సృష్టించండి:
[Unit]
Description=myapp docker compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
RequiresMountsFor=/srv/myapp/data
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/srv/myapp
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.targetదాన్ని enable చేసి start చేయండి:
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
systemctl status myapp.serviceసరిగ్గా పనిచేసే unit Active: active (exited) ను చూపిస్తుంది. మొదటిసారి చూసినప్పుడు అది తప్పుగా అనిపిస్తుంది. కానీ అదే సరైనది: RemainAfterExit=yes తో ఉన్న Type=oneshot అంటే unit తన commandను అమలు చేసింది, command పూర్తయింది, మరియు systemd unitను activeగా ఉంచుతుంది, తద్వారా shutdown సమయంలో ExecStop నడుస్తుంది.
ప్రతి lineకు కారణం ఉంది. Requires=docker.service అంటే dead socketపై docker compose నడపకుండా unit వెంటనే విఫలమవుతుంది. After= క్రమాన్ని నిర్దేశిస్తుంది, ఎందుకంటే Requires= ఒక్కటే ఆ పని చేయదు. RequiresMountsFor= systemdను ఆ pathకు సంబంధించిన mount unitను చేర్చి, అది సిద్ధమయ్యే వరకు వేచి ఉండేలా చేస్తుంది. restart policyకు బదులుగా unitను ఉపయోగించడానికి ఇదే ప్రధాన కారణం. పెద్ద image ఇంకా pull అవుతున్నప్పుడు start jobను systemd నిలిపివేయకుండా TimeoutStartSec=0 నిర్ధారిస్తుంది.
రెండు విధానాలను కలిపి ఉపయోగించడం గురించి ఒక గమనిక. restart policiesను host process managerతో కలపవద్దని Docker documentation సూచిస్తుంది. ఈ హెచ్చరిక container processను నేరుగా పర్యవేక్షించే process managerకు సంబంధించినది. Daemon కూడా అదే పని చేయడానికి ప్రయత్నిస్తున్నప్పుడు, ఆ process manager containerను restart చేస్తుంది. Type=oneshot unit ఏదీ పర్యవేక్షించదు. అందువల్ల ఈ unitతో పాటు compose fileలో restart: unless-stopped ఉంచడం సురక్షితం, మరియు అదే మీకు కావలసింది. Boot సమయంలో క్రమాన్ని systemd నిర్వహిస్తుంది. తెల్లవారుజామున 3 గంటలకు container crash అయితే, daemon దాన్ని నిర్వహిస్తుంది.
నిజమైన రీబూట్తో ధృవీకరించండి
నిజమైన పరీక్షకు ప్రత్యామ్నాయం లేదు. systemctl restart docker మౌంట్ల క్రమాన్ని పరీక్షించదు. అలాగే docker compose down తర్వాత docker compose up -d అమలు చేయడం ద్వారా బూట్కు సంబంధించిన ఏ అంశమూ పరీక్షించబడదు.
sudo rebootవేచి ఉండి, మళ్లీ కనెక్ట్ చేసి, ఈ క్రమంలో తనిఖీ చేయండి:
uptime
systemctl is-active docker
docker compose psuptime ద్వారా మీరు నిజంగా రీబూట్ అయిన యంత్రాన్ని పరిశీలిస్తున్నారని నిర్ధారించవచ్చు. stack directory నుంచి అమలు చేసే docker compose ps, ప్రతి service ను running స్థితిలో మరియు యంత్రం uptime కు దగ్గరగా ఉండే uptime తో చూపాలి. Exited చూపిస్తున్న service ను పరిశీలించాలి.
ఏదైనా ప్రారంభం కాకపోతే, daemon log లో బూట్ సమయంలో జరిగిన వివరాలు ఉంటాయి:
journalctl -u docker.service -b --no-pager | tail -50unit ద్వారా నిర్వహించబడే stack కోసం, journalctl -u myapp.service -b --no-pager బూట్ సమయంలో వచ్చిన ఖచ్చితమైన docker compose output ను చూపుతుంది. ఇందులో విఫలమైన image pull లేదా కనిపించని .env file కూడా ఉంటాయి.
ఆటో-స్టార్ట్ను నిశ్శబ్దంగా ఆపే అంశాలు
docker compose runతో సృష్టించిన కంటైనర్లకు ఫైల్లోని restart policy ఎప్పటికీ వర్తించదు. Compose వాటిని one-off కంటైనర్లుగా పరిగణిస్తుంది. ఏదైనా service తన policyని పట్టించుకోనట్లు కనిపిస్తే, అది upకు బదులుగా runతో ప్రారంభించబడిందో తనిఖీ చేయండి.
volumeలోని relative path లేదా env_file entryలోని relative path, compose file ఉన్న directoryకి సంబంధించి పరిష్కరించబడుతుంది. ఇది మీ shell నుంచి పనిచేస్తుంది. WorkingDirectoryను సెట్ చేసే unit నుంచి కూడా పనిచేస్తుంది. WorkingDirectory లేని unit నుంచి ఇది విఫలమవుతుంది, ఎందుకంటే అప్పుడు working directory /గా ఉంటుంది.
Rootless Docker వేరే సందర్భం. daemon ఒక user serviceగా నడుస్తుంది. ఆ user కోసం చివరి session ముగిసినప్పుడు user service ఆగిపోతుంది. దాన్ని ఆ user కోసం enable చేసి, ఎవరూ login చేయకపోయినా అది నడుస్తూ ఉండేలా అనుమతించండి:
systemctl --user enable docker
sudo loginctl enable-linger $USERenable-linger లేకపోతే, మీరు logout చేసినప్పుడు rootless daemon ఆగిపోతుంది. దానితో పాటు కంటైనర్లు కూడా ఆగిపోతాయి. ఇది restart policy పనిచేయనట్లుగా కనిపిస్తుంది.
ఇంకో విషయం. Automatic security updates serverను నిర్ణీత గంటకు reboot చేయవచ్చు. మీ stack స్వయంగా తిరిగి ప్రారంభమైతేనే అది ఉపయోగకరం. కొత్త machineలో దీన్ని ఏర్పాటు చేయడం, కొత్త VPSలో మొదటి పది నిమిషాల్లో చేయాల్సిన ఇతర మొదటి-గంట పనులతో కలిపి చేయాలి.
FAQ
restart: always మరియు restart: unless-stopped మధ్య తేడా ఏమిటి?
కంటైనర్ స్వయంగా ఆగిపోయినప్పుడు రెండూ దాన్ని మళ్లీ ప్రారంభిస్తాయి. మీరు కంటైనర్ను చేతితో ఆపిన తర్వాత వాటి ప్రవర్తనలో తేడా ఉంటుంది. always తో, Docker daemon తదుపరి సారి ప్రారంభమైనప్పుడు కంటైనర్ మళ్లీ ప్రారంభమవుతుంది. అందువల్ల reboot మీ చేతితో చేసిన stop చర్యను రద్దు చేస్తుంది. unless-stopped తో, కంటైనర్ను ఉద్దేశపూర్వకంగా ఆపారని daemon గుర్తుంచుకుని, దాన్ని అలాగే ఆపివేస్తుంది. కంటైనర్ మళ్లీ ప్రారంభం కాకుండా ఉండాలని ప్రత్యేకంగా కోరుకోకపోతే unless-stopped ఉపయోగించండి.
restart: unless-stopped జోడించినా reboot తర్వాత కంటైనర్ ఇంకా ప్రారంభం కావడం లేదు. ఎందుకు?
ఈ policy fileలో కాకుండా కంటైనర్పైనే ఉంటుంది. ఇప్పటికే ఉన్న కంటైనర్ను YAML మార్చడం ద్వారా update చేయలేరు. Compose దాన్ని మళ్లీ సృష్టించేందుకు docker compose up -d అమలు చేయండి. తర్వాత docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' $(docker compose ps -q app) తో నిర్ధారించండి. అది no చూపిస్తే, మీ మార్పుకు ముందే ఆ కంటైనర్ సృష్టించబడింది. మరో సాధారణ కారణం docker.service enable చేయకపోవడం. దీన్ని systemctl is-enabled docker తో తనిఖీ చేయవచ్చు.
నేను restart policies ఉపయోగిస్తున్నప్పుడు systemd unit అవసరమా?
సాధారణంగా అవసరం లేదు. కేవలం network అవసరమైన stackకు restart policy సరిపోతుంది. చాలా stackలు ఈ విధంగానే ఉంటాయి. Docker daemon ప్రారంభమైనప్పుడు సిద్ధంగా లేని వనరుపై కంటైనర్లు ఆధారపడితే unitను జోడించండి. ఉదాహరణకు external disk, encrypted volume, NFS share లేదా VPN interface. restart policy వ్యక్తం చేయలేని ప్రారంభ క్రమాన్ని unit After= మరియు RequiresMountsFor= ద్వారా నిర్దేశిస్తుంది.
తదుపరి rebootలో stack మళ్లీ ప్రారంభం కాకుండా దాన్ని శాశ్వతంగా ఎలా ఆపాలి?
unless-stopped తో docker compose stop సరిపోతుంది. ఎందుకంటే చేతితో ఆపిన కంటైనర్ను daemon మళ్లీ ప్రారంభించినప్పుడు తిరిగి ప్రారంభించదు. always తో stop మాత్రమే సరిపోదు. reboot తర్వాత కంటైనర్ మళ్లీ ప్రారంభమవుతుంది. docker compose down అమలు చేయండి. ఇది కంటైనర్లను తొలగిస్తుంది. లేదా ముందుగా docker update --restart no my-container తో policyని మార్చండి. systemd unit stackను నిర్వహిస్తే sudo systemctl disable myapp.service కూడా అమలు చేయండి. లేకపోతే unit దాన్ని మళ్లీ ప్రారంభిస్తుంది.