Docker Compose సేవలు boot సమయంలో auto-start చేయడం
reboot తర్వాత Docker Compose సేవలు తిరిగి రావాలంటే restart policies ఎలా అమలు చేయాలి, on-failure ఎందుకు సరిపోదు, systemd unit ఎప్పుడు అవసరమో తెలుసుకోండి.
సంక్షిప్త సమాధానం
రెండు షరతులు ఒకేసారి నెరవేరితే Docker Compose సేవలు boot సమయంలో ప్రారంభమవుతాయి. Docker daemon ను system service గా enabled చేసి ఉండాలి. అలాగే ఫైల్లోని ప్రతి సేవకు unless-stopped లేదా always restart policy ఉండాలి. ప్రతి సేవకు 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 సెట్ చేయండి
ఈ policy ప్రతి service కు ఒక్కో line గా ఉంటుంది. Global switch లేదు. అందువల్ల మీరు మర్చిపోయిన service reboot తర్వాత down గానే ఉంటుంది. Stack లోని మిగతా services ప్రారంభమవుతాయి.
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:దాన్ని apply చేసిన తర్వాత, running container నుంచి policy ను మళ్లీ చదవండి:
docker compose up -d
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' $(docker compose ps -q app)అది unless-stopped ను ప్రింట్ చేస్తుంది. no ప్రింట్ అయితే, file edit చేయబడింది కానీ container ఎప్పుడూ recreate కాలేదు.
ఇదే అత్యంత సాధారణ వైఫల్యం. Restart policy container లో నిల్వ ఉంటుంది; YAML file లో కాదు. ఇప్పటికే ఉన్న container కు సంబంధించిన compose.yaml ను edit చేయడం వల్ల ఆ container పై ఎలాంటి మార్పు ఉండదు. docker compose restart కూడా సహాయపడదు, ఎందుకంటే అది అదే container object ను ఆపి మళ్లీ ప్రారంభిస్తుంది; దాని configuration ను మార్చదు. docker compose up -d మాత్రమే file ను running containers తో పోల్చి, policy మారిందని గుర్తించి, వాటిని recreate చేస్తుంది.
ప్రస్తుతం recreate చేయకూడని container కోసం policy ను నేరుగా మార్చండి:
docker update --restart unless-stopped my-containerఅయినా YAML file ను కూడా edit చేయండి. docker update live container ను మార్చుతుంది. తరువాతి docker compose up -d file ను చదివి పాత విలువను మళ్లీ అమలు చేస్తుంది.
ప్రతి restart value వాస్తవంగా ఏమి చేస్తుంది
Docker నాలుగు values ను నిర్వచిస్తుంది. వాటి మధ్య తేడా machine reboot అయినప్పుడు లేదా daemon restart అయినప్పుడు మాత్రమే కనిపిస్తుంది.
nodefault value. ఏ పరిస్థితిలోనూ container స్వయంచాలకంగా restart కాదు.alwayscontainer ఆగిన ప్రతిసారీ దాన్ని restart చేస్తుంది. మీరు దాన్ని manualగా stop చేసినా, Docker daemon తదుపరిసారి start అయినప్పుడు అది మళ్లీ ప్రారంభమవుతుంది. ఇది తరచుగా ఆశ్చర్యానికి గురి చేస్తుంది: గత వారం ఉద్దేశపూర్వకంగా stop చేసిన container, reboot తర్వాత మళ్లీ running స్థితిలో ఉంటుంది.unless-stopped,alwaysలాగే పనిచేస్తుంది. అయితే manualగా stop చేసిన container daemon restart సమయంలో కూడా stopped స్థితిలోనే ఉంటుంది. అప్పుడప్పుడు maintenance కోసం నిలిపివేసే serviceకు ఇది సరైన value.on-failurecontainer non-zero exit code తో exit అయినప్పుడు మాత్రమే దాన్ని restart చేస్తుంది.restart: on-failure:3లో చూపినట్లుగా, ప్రయత్నాల సంఖ్యకు పరిమితి విధించవచ్చు.
Server up లో ఉన్నంతకాలం stack కూడా up లో ఉండాలంటే unless-stopped సరైన default. 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 నడిపే container అప్పుడప్పుడు crash కావచ్చు. అప్పుడు పరిమిత సంఖ్యలో retries కావాలి, restart loop మాత్రం వద్దు. ఎక్కువసేపు నడిచే service ను reboot తర్వాత కూడా కొనసాగించడానికి ఇది సరైన సాధనం కాదు.
Docker సేవ boot సమయంలో ప్రారంభమైతేనే restart policies పనిచేస్తాయి
restart policies ను 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 ను అందిస్తుంది. ఏదైనా process మొదటిసారి Docker API తో మాట్లాడినప్పుడు ఇది daemon ను అవసరానుసారం ప్రారంభిస్తుంది. docker.socket enabled గా కనిపించడంతో daemon సురక్షితంగా ఉందని భావించి, memory ఆదా చేయడానికి docker.service ను disable చేస్తారు. boot సమయంలో API ను పిలిచే process ఏదీ ఉండదు. అందువల్ల socket ను ఎవరూ access చేయరు, daemon ప్రారంభం కాదు, మీరు మొదటి docker command ను టైప్ చేసే వరకు container ఏదీ ప్రారంభం కాదు. Socket activation అనేది docker.service enabled గా ఉండటానికి ప్రత్యామ్నాయం కాదు.
systemd unit మెరుగైన ఎంపిక అయ్యే సందర్భాలు
Restart policies కి systemంలోని ఇతర భాగాలతో ప్రారంభ క్రమాన్ని నిర్ణయించే సామర్థ్యం ఉండదు. 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 సిద్ధంగా ఉండాలి. ఈ machine లోని ఇతర services మాదిరిగానే systemctl stop myapp మరియు systemctl start myapp పనిచేయాలి. లేదా shutdown సమయంలో daemon తో పాటు హఠాత్తుగా ఆపివేయకుండా, stack ను సక్రమంగా నిలిపివేయాలి. systemd units మీకు కొత్త అయితే, systemd service మరియు timer రాయడం file format ను మరింత వివరంగా వివరిస్తుంది.
systemd unit ను రాయడం
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 ను నడిపి పూర్తి చేసింది. Shutdown సమయంలో ExecStop నడిచేలా systemd unit ను active గా గుర్తించి ఉంచుతుంది.
ప్రతి line కు నిర్దిష్ట కారణం ఉంది. Requires=docker.service వల్ల dead socket పై docker compose నడపకుండా unit వెంటనే fail అవుతుంది. After= క్రమాన్ని నిర్దేశిస్తుంది, ఎందుకంటే Requires= ఒక్కటే క్రమాన్ని నిర్దేశించదు. RequiresMountsFor= ఆ path కు సంబంధించిన mount unit ను systemd load చేసి, అది సిద్ధమయ్యే వరకు వేచి ఉండేలా చేస్తుంది. Restart policy కంటే unit ను ఉపయోగించడానికి ఇదే ప్రధాన కారణం. పెద్ద image ఇంకా pull అవుతున్నప్పుడు start job ను systemd ఆపకుండా TimeoutStartSec=0 నిరోధిస్తుంది.
రెండు mechanisms ను కలిపి ఉపయోగించడం గురించి ఒక గమనిక. Host process manager తో restart policies ను కలపవద్దని Docker documentation సూచిస్తుంది. Daemon కూడా అదే పని చేయడానికి ప్రయత్నిస్తున్నప్పుడు, container process ను స్వయంగా supervise చేసి restart చేసే process manager గురించే ఆ హెచ్చరిక. Type=oneshot unit ఏదీ supervise చేయదు. అందువల్ల ఈ unit తో పాటు compose file లో restart: unless-stopped ఉంచడం సరైనదే; మీకు కావలసింది కూడా అదే. Boot సమయంలో క్రమాన్ని systemd నిర్వహిస్తుంది. తెల్లవారుజామున 3 గంటలకు crash అయ్యే container ను daemon నిర్వహిస్తుంది.
మీరు alive గా ఉంచేది stack కాకుండా సాధారణంగా ఎక్కువసేపు నడిచే process అయితే unit భిన్నంగా కనిపిస్తుంది. అప్పుడు దాని కింద daemon ఉండదు. కాబట్టి systemd యొక్క స్వంత Restart= నే supervising చేయాలి. systemd వెనుక headless గా dsh నడపడం dedicated user మరియు journal సహా ఆ నిర్మాణానికి పూర్తి ఉదాహరణను చూపిస్తుంది.
నిజమైన reboot తో నిర్ధారించండి
నిజమైన పరీక్షకు ప్రత్యామ్నాయం లేదు. systemctl restart docker ద్వారా mount ordering పరీక్షించబడదు. అలాగే docker compose down తర్వాత docker compose up -d అమలు చేయడం bootకు సంబంధించిన ఏ అంశాన్నీ పరీక్షించదు.
sudo rebootవేచి ఉండి, మళ్లీ కనెక్ట్ అయి, ఈ క్రమంలో తనిఖీ చేయండి:
uptime
systemctl is-active docker
docker compose psమీరు నిజంగా reboot అయిన machineను చూస్తున్నారని uptime నిర్ధారిస్తుంది. Stack directory నుంచి అమలు చేసే docker compose ps, ప్రతి serviceను running స్థితిలో మరియు machine uptimeకు దగ్గరగా ఉన్న uptimeతో చూపాలి. Exited చూపించే serviceను పరిశీలించాలి.
ఏదైనా ప్రారంభం కాకపోతే, daemon log boot windowకు సంబంధించిన సమాచారాన్ని కలిగి ఉంటుంది:
journalctl -u docker.service -b --no-pager | tail -50Unit ద్వారా నిర్వహించబడే stack కోసం, boot సమయంలో వచ్చిన ఖచ్చితమైన docker compose outputను journalctl -u myapp.service -b --no-pager చూపిస్తుంది. ఇందులో విఫలమైన image pull లేదా కనిపించని .env file కూడా ఉండవచ్చు. మీరు schedule చేసే rebootను మీరు స్వయంగా monitor చేస్తారు. అందువల్ల మిగిలిన rebootల గురించి unit మీకు తెలియజేయేలా చేయండి: స్వయంగా నిర్వహించే ntfy serverను సూచించే OnFailure= line, తిరిగి ప్రారంభం కాని stackను మీరు కొన్ని రోజుల తర్వాత గుర్తించే సమస్యగా కాకుండా push notificationగా మారుస్తుంది.
ఆటో-స్టార్ట్ను నిశ్శబ్దంగా విఫలమయ్యే అంశాలు
docker compose run తో సృష్టించిన containers కు file లోని restart policy వర్తించదు. Compose వాటిని one-off containers గా పరిగణిస్తుంది. ఏదైనా 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 చేసి, ఎవరూ logged in లేకపోయినా అది నడుస్తుండేలా అనుమతించండి:
systemctl --user enable docker
sudo loginctl enable-linger $USERenable-linger లేకపోతే, మీరు logout చేసినప్పుడు rootless daemon ఆగిపోతుంది. దానితో పాటు containers కూడా ఆగిపోతాయి. ఇది విఫలమైన restart policy లాగే కనిపిస్తుంది.
చివరి విషయం. Automatic security updates నిర్ణయించిన సమయంలో server ను reboot చేయవచ్చు. మీ stack స్వయంగా తిరిగి ప్రారంభమైతేనే ఇది ఉపయోగకరం. కొత్త machine లో దీన్ని ఏర్పాటు చేయడం, కొత్త VPS లో మొదటి పది నిమిషాలులోని ఇతర first-hour పనులతో కలిపి చేయాలి.
FAQ
restart: always మరియు restart: unless-stopped మధ్య తేడా ఏమిటి?
రెండూ container స్వయంగా ఆగిపోయినప్పుడు దాన్ని మళ్లీ ప్రారంభిస్తాయి. మీరు container ను చేతితో ఆపిన తర్వాత వాటి ప్రవర్తనలో తేడా ఉంటుంది. always ఉపయోగిస్తే, Docker daemon తదుపరి సారి ప్రారంభమైనప్పుడు container మళ్లీ ప్రారంభమవుతుంది. అంటే reboot మీ చేతితో చేసిన stop ను రద్దు చేస్తుంది. unless-stopped ఉపయోగిస్తే, container ను ఉద్దేశపూర్వకంగా ఆపారని daemon గుర్తుంచుకుని, దాన్ని అలాగే ఆపి ఉంచుతుంది. మళ్లీ ప్రారంభం కాకుండా ఉండే container మీకు ప్రత్యేకంగా అవసరం లేకపోతే unless-stopped ఉపయోగించండి.
నేను restart: unless-stopped జోడించాను. అయినా reboot తర్వాత container ఎందుకు ప్రారంభం కావడం లేదు?
ఈ policy file లో కాకుండా container పై అమలవుతుంది. ఇప్పటికే ఉన్న container ను YAML సవరించడం ద్వారా update చేయలేరు. Compose దాన్ని మళ్లీ సృష్టించేలా docker compose up -d అమలు చేయండి. తరువాత docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' $(docker compose ps -q app) తో నిర్ధారించండి. దాని output no అయితే, ఆ container మీరు చేసిన సవరణకు ముందే సృష్టించబడింది. మరో సాధారణ కారణం docker.service enable చేయకపోవడం. దీన్ని systemctl is-enabled docker తో తనిఖీ చేయవచ్చు.
నేను ఇప్పటికే restart policies ఉపయోగిస్తే systemd unit అవసరమా?
సాధారణంగా అవసరం లేదు. Network మాత్రమే అవసరమైన stack కు restart policy సరిపోతుంది. చాలా stack లకు ఇదే వర్తిస్తుంది. Docker daemon ప్రారంభమైనప్పుడు సిద్ధంగా లేని దానిపై containers ఆధారపడితే unit జోడించండి. ఉదాహరణకు external disk, encrypted volume, NFS share లేదా VPN interface. Restart policy వ్యక్తపరచలేని ordering ను unit After= మరియు RequiresMountsFor= ద్వారా అందిస్తుంది.
తదుపరి reboot లో stack మళ్లీ ప్రారంభం కాకుండా దాన్ని శాశ్వతంగా ఎలా ఆపాలి?
unless-stopped ఉపయోగించే సందర్భంలో docker compose stop సరిపోతుంది. ఎందుకంటే చేతితో ఆపిన container daemon మళ్లీ ప్రారంభమైనప్పుడు resume కాదు. always ఉపయోగిస్తే stop చేయడం సరిపోదు. reboot తర్వాత container మళ్లీ ప్రారంభమవుతుంది. docker compose down అమలు చేయవచ్చు. ఇది containers ను తొలగిస్తుంది. లేదా ముందుగా docker update --restart no my-container తో policy మార్చండి. systemd unit stack ను నిర్వహిస్తే sudo systemctl disable myapp.service కూడా అమలు చేయండి. లేకపోతే unit దాన్ని మళ్లీ ప్రారంభిస్తుంది.