Ubuntu 24.04లో Docker Compose సెటప్ చేయడం ఎలా?
Ubuntu 24.04లో Docker Engine మరియు Compose ప్లగిన్ ఇన్స్టాల్ చేయండి. ufw ఫైర్వాల్ సమస్యలను దాటవేస్తూ, రెండు సర్వీసుల compose.yml ఫైల్ను సురక్షితంగా ఎలా రాయాలో ఇక్కడ నేర్చుకోండి.
మీరు ఏమి నిర్మిస్తున్నారు
ఈ సైట్లోని దాదాపు అన్నింటికీ Docker Compose పునాదిగా ఉంటుంది. Nextcloud, Vaultwarden, n8n, Immich, Rocket.Chat, వంటి ప్రతి గైడ్ "ఈ compose ఫైల్ను రాయండి" అని మొదలవుతుంది, ఆ ఫైల్ అసలు అర్థం ఏమిటో ఈ పేజీ వివరిస్తుంది. మీరు Ubuntu 24.04 లో Docker యొక్క అధికారిక apt రిపోజిటరీ నుండి Docker Engine మరియు Compose ప్లగిన్ను ఇన్స్టాల్ చేస్తారు. ఆపై, ఒక వాస్తవమైన రెండు-సర్వీసుల స్టాక్ను (Miniflux అనే చిన్న RSS రీడర్ మరియు PostgreSQL) సిద్ధం చేస్తారు. ఎందుకంటే ఈ జంట పెద్ద అప్లికేషన్లు ఉపయోగించే ప్రతి పద్ధతిని కలిగి ఉంటుంది: పిన్ చేసిన ఇమేజ్లు, హెల్త్చెక్ ఉన్న డేటాబేస్, నేమ్డ్ వాల్యూమ్, .env ఫైల్లో రహస్యాలు (secrets), మరియు localhost కు మాత్రమే పరిమితం చేసిన పోర్ట్.
ఇన్స్టాలేషన్ ఐదు నిమిషాల్లో పూర్తవుతుంది. ఈ గైడ్లోని మిగిలిన భాగం తర్వాత ఇబ్బంది కలిగించే అంశాలను వివరిస్తుంది: docker గ్రూప్ అనేది root కు మరో పేరు అని, పబ్లిష్ చేసిన పోర్ట్లు మీ ufw నియమాలను దాటి నేరుగా వెళ్తాయని, మరియు docker compose down లోని ఒక ఫ్లాగ్ ఎటువంటి నిర్ధారణ అడగకుండానే మీ డేటాబేస్ను తొలగిస్తుందని తెలుసుకోవాలి.
ముందస్తు అవసరాలు: కొత్తగా ఇన్స్టాల్ చేసిన Ubuntu 24.04 KVM VPS, sudo అనుమతులు ఉన్న యూజర్, మరియు ఒక గిగాబైట్ లేదా అంతకంటే ఎక్కువ RAM. ఇప్పటికే Docker ఇన్స్టాల్ అయి ఉన్నా పర్వాలేదు, మొదటి విభాగంలో దేనిని తొలగించాలో వివరిస్తాము.
Ubuntu రిపోజిటరీ నుంచి కాకుండా Docker రిపోజిటరీ నుంచి ఇన్స్టాల్ చేయండి
మొదటి కమాండ్ అమలు చేసే ముందు రెండు తప్పుడు పద్ధతులను నివారించాలి. Ubuntu అందించే docker.io ప్యాకేజీ పనిచేస్తుంది, కానీ ఇది Docker యొక్క కొత్త releases కంటే వెనుకబడి ఉంటుంది మరియు ఇతర అప్లికేషన్లకు అవసరమైన plugin layout ను కలిగి ఉండదు. అలాగే, హైఫన్ ఉన్న docker-compose కమాండ్ పాత ట్యుటోరియల్స్ సూచించే పద్ధతి. పాత సర్వర్లలో ఈ కమాండ్ సాధారణంగా Python లో రాసిన Compose v1 ని సూచిస్తుంది; దీనిని Docker ఇప్పటికే నిలిపివేసింది (end of life), అందుకే ఆ ట్యుటోరియల్స్ పనిచేయవు. Docker ఇప్పటికీ Go భాషలో నిర్మించిన స్వతంత్ర docker-compose బైనరీని అందిస్తోంది, కానీ దాని ఇన్స్టాలేషన్ పేజీలోనే ఈ పద్ధతిని సిఫార్సు చేయడం లేదని, కేవలం పాత వెర్షన్ల అనుకూలత కోసం మాత్రమే ఉంచామని పేర్కొంది. ప్రస్తుతం Compose అంటే docker compose (స్పేస్తో), ఇది ఒక CLI plugin, దీనిని engine ఉన్న రిపోజిటరీ నుంచే ఇన్స్టాల్ చేయాలి.
ఒకవేళ వీటిలో ఏవైనా ఇప్పటికే సర్వర్లో ఉంటే, వాటిని ముందుగా తొలగించండి. Ubuntu అందించే docker-compose-v2 మరియు docker-buildx ప్యాకేజీలను కూడా తొలగించండి, తద్వారా అన్నీ ఒకే రిపోజిటరీ నుంచి వస్తాయి:
sudo apt remove -y docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runcకొత్త VPS లో Package 'docker.io' is not installed, so not removed అనేది సాధారణ అవుట్పుట్. ఇప్పుడు Docker రిపోజిటరీని జోడించి, ఇన్స్టాల్ చేయండి:
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginమూడు పొరలను (layers) సరిచూసుకోండి:
docker --version
docker compose version
sudo docker run --rm hello-worldమొదటి రెండు కమాండ్లు version strings ను ప్రింట్ చేస్తాయి, Docker Compose version v5.x.x అనేది మీరు పాత v1 బైనరీ కాకుండా plugin ను ఉపయోగిస్తున్నారని నిర్ధారిస్తుంది. పాత compose file format వెర్షన్లతో గందరగోళం కలగకుండా ఉండటానికి, ఈ plugin వెర్షన్ డిసెంబర్ 2025లో v2 నుంచి నేరుగా v5 కి మారింది (v3, v4 లను దాటవేసింది). కాబట్టి, v2.x.x అని చూపించే గైడ్లు కూడా ఇదే సాధనాన్ని సూచిస్తాయి. hello-world రన్ చేసినప్పుడు చివరగా Hello from Docker! అని రావాలి. ఈ ప్యాకేజీ సర్వర్ బూట్ అయినప్పుడు సేవను ఆటోమేటిక్గా ప్రారంభిస్తుంది; systemctl is-enabled docker కమాండ్ enabled అని ప్రింట్ చేస్తుంది.
docker గ్రూప్ అంటే root, కాబట్టి జాగ్రత్తగా నిర్ణయం తీసుకోండి
ప్రస్తుతం ప్రతి docker కమాండ్కు sudo అవసరం, ఎందుకంటే /var/run/docker.sock వద్ద ఉన్న డెమోన్ సాకెట్ (daemon's socket) యాజమాన్యం root మరియు docker గ్రూపుకు ఉంటుంది. ఈ గ్రూపులో సభ్యత్వం లేకపోతే, Docker కు సంబంధించి అత్యధికంగా వెతికే ఈ ఎర్రర్ వస్తుంది:
permission denied while trying to connect to the Docker daemon socket at
unix:///var/run/docker.sockదీనికి ప్రామాణిక పరిష్కారం:
sudo usermod -aG docker $USERగ్రూప్ సభ్యత్వం లాగిన్ అయినప్పుడు వర్తిస్తుంది, కాబట్టి మీరు ప్రస్తుతం వాడుతున్న షెల్ (shell) లో ఈ ఎర్రర్ అలాగే కనిపిస్తుంది. ఈ సెషన్ కోసం newgrp docker రన్ చేయండి, లేదా లాగ్ అవుట్ చేసి మళ్ళీ లాగిన్ అవ్వండి; అప్పుడు id కమాండ్ మీ గ్రూపుల జాబితాలో docker ను చూపించాలి.
ఇక అసలు విషయం, స్పష్టంగా చెప్పాలంటే: docker గ్రూపులో సభ్యత్వం ఉండటం అంటే హోస్ట్ మెషీన్ మీద root పర్మిషన్లు ఉండటమే. ఇది "root లాంటిది" లేదా "కొంచెం ఎక్కువ పవర్" కాదు, ఇది పూర్తిగా root. ఈ గ్రూపులో ఉన్న ఎవరైనా docker run --rm -it -v /:/host alpine chroot /host కమాండ్ను రన్ చేసి, పాస్వర్డ్ అడగకుండానే మొత్తం ఫైల్సిస్టమ్ను తమ ఆధీనంలోకి తీసుకోవచ్చు. ఈ గ్రూప్ కేవలం సౌలభ్యం కోసం మాత్రమే ఉంది, భద్రత (containment) కోసం కాదు.
Docker యొక్క rootless మోడ్ దీనికి సరైన ప్రత్యామ్నాయం, ఇందులో డెమోన్ మీ unprivileged యూజర్ ఖాతాతోనే రన్ అవుతుంది. దీనివల్ల కొన్ని పరిమితులు ఉన్నాయి: 1024 కంటే తక్కువ ఉన్న పోర్ట్లకు అదనపు సెటప్ అవసరం, నెట్వర్కింగ్ ఒక userspace shim ద్వారా జరుగుతుంది కాబట్టి కొంత పనితీరు తగ్గుతుంది, మరియు కొన్ని ఇమేజ్లు నిజమైన root లేకుండా సరిగ్గా పనిచేయవు. ఒకే అడ్మిన్ ఉన్న VPS లో, ఇప్పటికే sudo పర్మిషన్లు ఉన్న యూజర్కు ఈ గ్రూప్ మార్పు వల్ల ఆచరణలో పెద్దగా తేడా ఉండదు. ఈ గైడ్లో ఉన్నవన్నీ ఇదే పద్ధతిని అనుసరిస్తాయి, కానీ దీన్ని ఎప్పుడూ sudo కంటే తక్కువ స్థాయి పర్మిషన్ అని భావించకండి.
Compose ఫైల్ నిర్మాణం
ప్రతి stack కు ఒక ప్రత్యేక డైరెక్టరీని కేటాయించండి. ఆ డైరెక్టరీ పేరు ప్రాజెక్ట్ పేరుగా మారుతుంది, ఇది కంటైనర్లు, నెట్వర్క్లు మరియు వాల్యూమ్లకు ప్రిఫిక్స్గా పనిచేస్తుంది:
sudo mkdir -p /opt/miniflux && sudo chown $USER /opt/miniflux && cd /opt/minifluxcompose.yml ను సృష్టించండి (ఇది ఆధునిక పద్ధతి; docker-compose.yml కూడా పనిచేస్తుంది). పాత version: కీని వదిలేయండి, ఇది కాలం చెల్లినది మరియు Compose దీనిని గుర్తిస్తే హెచ్చరికను జారీ చేస్తుంది.
services:
miniflux:
image: miniflux/miniflux:2.2.9
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
- DATABASE_URL=postgres://miniflux:${POSTGRES_PASSWORD}@db/miniflux?sslmode=disable
- RUN_MIGRATIONS=1
- CREATE_ADMIN=1
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=miniflux
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "miniflux", "-d", "miniflux"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:పైన ఉన్న ప్రతి లైన్ ఒక నిర్ణయం. వాటిని ఒక్కొక్కటిగా అమలు చేయండి.
ఇమేజ్ వెర్షన్లను పిన్ చేయండి, :latest మరియు pull వాడటం అంటే పర్యవేక్షణ లేని అప్గ్రేడ్
postgres:latest వద్దు, postgres:16-alpine వాడండి. ట్యాగ్ అనేది స్థిరమైనది కాదు: మీరు pull చేసిన ప్రతిసారీ :latest అనేది మెయింటైనర్ చివరగా పుష్ చేసిన ఇమేజ్కు మారుతుంది. మీరు నేర్చుకోబోయే సాధారణ అప్గ్రేడ్ అలవాటు docker compose pull && docker compose up -d తో దీనిని కలిపితే, upstream వారు కొత్త వెర్షన్ విడుదల చేసినప్పుడల్లా :latest ఆటోమేటిక్గా మేజర్ వెర్షన్ జంప్లను తీసుకుంటుంది. PostgreSQL విషయంలో ఇది ఊహ కాదు: 16 నుంచి 17కి అకస్మాత్తుగా మారితే, డేటా డైరెక్టరీ అనుకూలంగా లేక కంటైనర్ క్రాష్-లూప్లోకి వెళ్తుంది. ఎందుకంటే Postgres మేజర్ అప్గ్రేడ్లకు కేవలం రీస్టార్ట్ సరిపోదు, dump మరియు restore అవసరం.
కనీసం మేజర్ వెర్షన్ను పిన్ చేయండి (postgres:16-alpine అనేది 16.x ప్యాచ్ రిలీజ్లను అనుసరిస్తుంది), మరియు అప్లికేషన్లను miniflux/miniflux:2.2.9 వంటి ఖచ్చితమైన రిలీజ్కు పిన్ చేయండి. ప్రాజెక్ట్ యొక్క రిలీజ్ పేజీని తనిఖీ చేసి, ఫైల్ రాసే సమయంలో ఏది కరెంట్గా ఉంటే దానిని వాడండి. అప్పుడు అప్గ్రేడ్ అనేది మీరు ఉద్దేశపూర్వకంగా చేసే ఒక లైన్ మార్పుగా మారుతుంది, ఇది git diff లో కనిపిస్తుంది.
127.0.0.1 కి పబ్లిష్ చేయండి, ఎందుకంటే Docker ufw ను దాటవేస్తుంది
"127.0.0.1:8080:8080", హోస్ట్ అడ్రస్, హోస్ట్ పోర్ట్, కంటైనర్ పోర్ట్. చాలా ట్యుటోరియల్స్ "8080:8080" అని రాస్తాయి, ఇది 0.0.0.0:8080:8080 కి సంక్షిప్త రూపం: అంటే పబ్లిక్ ఇంటర్ఫేస్తో సహా అన్ని ఇంటర్ఫేస్లలో వినడం.
ఇక్కడే చిక్కు ఉంది, ఇది దాదాపు అందరినీ ఒకసారి ఇబ్బంది పెడుతుంది. Docker ఒక పోర్ట్ను పబ్లిష్ చేసేటప్పుడు, ప్యాకెట్ ఫిల్టరింగ్కు ముందే దాని గమ్యాన్ని కంటైనర్ యొక్క అంతర్గత IPకి మార్చే DNAT రూల్ను రాస్తుంది. కాబట్టి ప్యాకెట్ FORWARD మార్గంలో వెళ్తుంది మరియు మీ ufw రూల్స్ ఉన్న INPUT ని ఎప్పటికీ తాకదు. sudo ufw deny 8080 సక్సెస్ అని చూపిస్తుంది, ufw status పోర్ట్ డినై అయినట్లు చూపిస్తుంది, కానీ సర్వీస్ మాత్రం మొత్తం ఇంటర్నెట్కు సమాధానం ఇస్తుంది. మీ ఫైర్వాల్ పాడవ్వలేదు; అది డిజైన్ పరంగానే దాటవేయబడుతోంది. Docker ఎందుకు ufw ను దాటవేస్తుంది మరియు కంటైనర్ ట్రాఫిక్ను ఎలా ఫిల్టర్ చేయాలి అనే గైడ్ ఈ మెకానిజం గురించి మరియు పబ్లిక్గా ఉండాల్సిన పోర్ట్ల కోసం DOCKER-USER పరిష్కారం గురించి వివరిస్తుంది.
ఈ సమస్యను పూర్తిగా తొలగించే అలవాటు: ప్రత్యేక కారణం లేకపోతే పబ్లిష్ చేసిన పోర్ట్లను 127.0.0.1 కి బైండ్ చేయండి, మరియు ప్రపంచానికి కనిపించాల్సిన వాటి కోసం ముందు ఒక reverse proxy ని ఉంచండి. ఈ పేజీ తర్వాత వచ్చే Traefik reverse proxy guide సరిగ్గా ఇదే చేస్తుంది, అంటే పోర్ట్ 80 మరియు 443 లను కలిగి ఉండి, TLS తో హోస్ట్నేమ్ ఆధారంగా మిగిలిన వాటికి రూట్ చేసే ఒక కంటైనర్. (పాత Traefik v2 సెటప్ నుంచి వస్తున్నారా? Traefik v2 to v3 migration guide లో మార్పులు మరియు రూల్స్ గురించి చూడవచ్చు.)
స్టాక్ ప్రారంభించిన తర్వాత బైండ్ను ధృవీకరించండి: sudo ss -tlnp | grep 8080 అనేది 0.0.0.0:8080 లేదా *:8080 కాకుండా, 127.0.0.1:8080 ని చూపాలి.
Named volumes vs bind mounts
db-data:/var/lib/postgresql/data అనేది ఒక named volume: Docker ఒక డైరెక్టరీని /var/lib/docker/volumes/ కింద సృష్టించి, దానిని కంటైనర్లోకి మౌంట్ చేస్తుంది. దీనికి ప్రత్యామ్నాయం bind mount, ./data:/var/lib/postgresql/data, ఇది హోస్ట్పై మీరు ఎంచుకున్న పాత్ను మ్యాప్ చేస్తుంది.
ఆచరణలో పనిచేసే విభజన ఇది: కంటైనర్లు మాత్రమే తాకే డేటా కోసం named volumes వాడండి, ముఖ్యంగా డేటాబేస్ల కోసం, ఎందుకంటే ఇమేజ్ ఆశించే ఓనర్షిప్తో Docker వాల్యూమ్ను ఇనిషియలైజ్ చేస్తుంది మరియు ఫైల్ పర్మిషన్లు సరిగ్గా పనిచేస్తాయి. మీరు హోస్ట్ నుంచి తాకే ఫైల్స్ కోసం bind mounts వాడండి, అంటే మీరు ఎడిట్ చేసే కాన్ఫిగరేషన్ ఫైల్స్, మీరు rsync చేసే మీడియా లైబ్రరీ, లేదా పాత్ స్పష్టంగా ఉండాలనుకునే ఏదైనా ఫైల్. Bind-mount విఫలమవ్వడానికి ప్రధాన కారణం ఓనర్షిప్: ఇమేజ్ దాని ప్రాసెస్ను ఒక స్థిరమైన UIDతో రన్ చేస్తుంది (Miniflux ఇమేజ్ UID 65534 తో రన్ అవుతుంది, postgres:16-alpine UID 70 కి మారుతుంది), మీ హోస్ట్ డైరెక్టరీ UID 1000 కి చెంది ఉంటుంది, అప్పుడు యాప్ స్టార్టప్లో permission denied ఎర్రర్తో ఆగిపోతుంది. Named volumes ఈ రకమైన బగ్లను దాదాపు తొలగిస్తాయి, అయితే డేటా Docker-నిర్వహించే పాత్లో ఉంటుంది.
environment మరియు .env, secrets ను git లో ఉంచకండి
మీ షెల్ ఆ వేరియబుల్ను డిఫైన్ చేయనప్పుడు మాత్రమే, compose.yml పక్కన ఉన్న .env ఫైల్ నుంచి Compose ${POSTGRES_PASSWORD} ని నింపుతుంది: మీ షెల్ ఎన్విరాన్మెంట్లో ఎక్స్పోర్ట్ చేసిన విలువ .env ఫైల్ కంటే ప్రాధాన్యత పొందుతుంది. కాబట్టి పాత ప్రయోగం నుంచి మిగిలిపోయిన export POSTGRES_PASSWORD=... ఫైల్ను ఓవర్రైడ్ చేస్తుంది, మరియు ఏ విలువ గెలిచిందో docker compose config (కింద) చూపిస్తుంది. ఫైల్ను సృష్టించండి:
cat > .env <<'EOF'
POSTGRES_PASSWORD=change-me-to-something-long
ADMIN_PASSWORD=change-me-too
EOF
chmod 600 .env
echo ".env" >> .gitignoreopenssl rand -hex 24 తో నిజమైన విలువలను జనరేట్ చేయండి. Base64 కాకుండా Hex వాడండి: ఈ పాస్వర్డ్ DATABASE_URL కనెక్షన్ స్ట్రింగ్లోకి వెళ్తుంది, మరియు base64 ఇచ్చే /, +, మరియు = క్యారెక్టర్లు URL పార్సింగ్ను పాడు చేస్తాయి. ఇది సింటాక్స్ ఎర్రర్ కాకుండా అథెంటికేషన్ ఎర్రర్గా కనిపిస్తుంది. .gitignore లైన్ను మొదటి కమిట్కు ముందే చేర్చండి: compose ఫైల్ను పబ్లిష్ చేయడం సురక్షితం, కానీ .env ఫైల్ ఎప్పటికీ సురక్షితం కాదు, git హిస్టరీలోకి వెళ్ళిన సీక్రెట్ను మీరు మార్చాల్సి ఉంటుంది. ఒక వేరియబుల్ లేకుండా స్టాక్ను ప్రారంభిస్తే, Compose హెచ్చరిస్తుంది మరియు ఖాళీ స్ట్రింగ్తో కొనసాగుతుంది, Postgres పాస్వర్డ్ విషయంలో ఇది డిప్లాయ్మెంట్ను పాడు చేస్తుంది:
WARN[0000] The "POSTGRES_PASSWORD" variable is not set. Defaulting to a blank string.docker compose config అనేది పూర్తిగా ఇంటర్పోలేట్ చేయబడిన ఫైల్ను ప్రింట్ చేస్తుంది, కంటైనర్లు ఏమి అందుకుంటాయో తనిఖీ చేయడానికి ఇది వేగవంతమైన మార్గం; దీని అవుట్పుట్లో మీ సీక్రెట్స్ కూడా ఉంటాయని గుర్తుంచుకోండి.
depends_on దేనికోసం ఆగదు, healthcheck జోడిస్తే తప్ప
కేవలం depends_on: [db] అనేది స్టార్ట్ అయ్యే క్రమాన్ని మాత్రమే నియంత్రిస్తుంది: Compose మొదట Postgres ను, ఆ తర్వాత యాప్ను ప్రారంభిస్తుంది, కానీ Postgres కనెక్షన్లను స్వీకరించడానికి అప్పటికే కొన్ని సెకన్లు పడుతుంది. యాప్ డేటాబేస్ను తాకి, విఫలమై, క్రాష్ అవుతుంది లేదా రీట్రై అవుతుంది.
నమ్మదగిన వెర్షన్ పైన ఉన్న ఫైల్లో ఉంది: db సర్వీస్ ఒక healthcheck ని డిఫైన్ చేస్తుంది (Postgres దీని కోసం pg_isready ని అందిస్తుంది), మరియు యాప్ condition: service_healthy తో depends_on ని డిక్లేర్ చేస్తుంది. Compose డేటాబేస్ను స్టార్ట్ చేసి, ప్రతి 10 సెకన్లకు చెక్ చేస్తుంది, చెక్ పాస్ అయిన తర్వాతే Miniflux ను స్టార్ట్ చేస్తుంది. డేటాబేస్ హెల్తీగా మారకపోతే (తప్పు పాస్వర్డ్, కరప్ట్ వాల్యూమ్), యాప్ స్టార్ట్ అవ్వదు మరియు ఏ డిపెండెన్సీ విఫలమైందో Compose మీకు చెబుతుంది:
dependency failed to start: container miniflux-db-1 is unhealthyఆ మెసేజ్ మిమ్మల్ని docker compose logs db వైపు చూపిస్తుంది, అక్కడే అసలైన ఎర్రర్ ఉంటుంది.
restart: unless-stopped
రెండు సర్వీసులపై restart: unless-stopped అంటే కంటైనర్లు క్రాష్ అయిన తర్వాత మరియు VPS రీబూట్ తర్వాత తిరిగి వస్తాయి, కానీ మీరు ఉద్దేశపూర్వకంగా docker compose stop రన్ చేస్తే అవి ఆగిపోతాయి. ప్రత్యామ్నాయమైన always మాన్యువల్గా ఆపిన తర్వాత కూడా కంటైనర్లను పునరుద్ధరిస్తుంది, ఇది సాధారణంగా మనం కోరుకునేది కాదు. రీస్టార్ట్ పాలసీ లేకపోతే, ఉదయం 4 గంటలకు జరిగే కెర్నల్-అప్డేట్ రీబూట్ మీ సర్వీసులను మీరు గమనించే వరకు ఆపివేస్తుంది.
రోజువారీ క్రియలు
రోజువారీ నిర్వహణ అంతా ఐదు కమాండ్లతో జరుగుతుంది, వీటిని ప్రాజెక్ట్ డైరెక్టరీ నుండి రన్ చేయాలి.
docker compose up -d # create and start; idempotent, recreates only what changed
docker compose ps # status, ports, and health of this project's containers
docker compose logs -f miniflux # follow one service's logs; --tail 100 for recent history
docker compose pull && docker compose up -d # upgrade to the pinned tags
docker compose down # stop and remove containers and the networkup -d ను పదేపదే రన్ చేయడం సురక్షితం, ఇది ఫైల్ను వాస్తవ స్థితితో పోల్చి (diff), కాన్ఫిగరేషన్ లేదా ఇమేజ్ మారిన సర్వీసులను మాత్రమే ప్రభావితం చేస్తుంది. అప్గ్రేడ్ జంట (pair) మీరు పిన్ చేసిన ట్యాగ్లు ప్రస్తుతం దేనిని సూచిస్తున్నాయో వాటిని పొందుతుంది: postgres:16-alpine కింద ప్యాచ్ రిలీజ్లు వస్తాయి, మీరు ఎడిట్ చేసే వరకు ఖచ్చితమైన పిన్ (exact pin) కోసం ఏమీ మారదు, అదే దీని ముఖ్య ఉద్దేశ్యం. అప్గ్రేడ్ల తర్వాత పాత ఇమేజ్లు పేరుకుపోతాయి; docker image prune -f తో డిస్క్ స్థలాన్ని తిరిగి పొందండి.
ఇక ప్రమాదకరమైన కమాండ్ గురించి, గట్టిగా చెప్పాలంటే: docker compose down సురక్షితమైనది, కంటైనర్లు మరియు నెట్వర్క్ తాత్కాలికమైనవి, మీ డేటా వాల్యూమ్లో ఉంటుంది. docker compose down -v పేరున్న వాల్యూమ్లను కూడా తొలగిస్తుంది. అంటే మీ డేటాబేస్ తక్షణమే పోతుంది, ఎటువంటి నిర్ధారణ అడగదు మరియు దీనిని వెనక్కి తీసుకోవడం (undo) సాధ్యం కాదు. -v ఫ్లాగ్ ప్రయోగాల కోసం మాత్రమే; నిజమైన డేటా ఉన్న స్టాక్పై, దీనిని మీరు rm -rf ని ఎలా చూస్తారో అలాగే చూడండి. /var/lib/docker/volumes/ కింద ఎటువంటి ట్రాష్ క్యాన్ (trash can) ఉండదు.
రన్ అవుతున్న కంటైనర్ లోపల ఒకసారి షెల్ పొందడానికి: docker compose exec db psql -U miniflux మిమ్మల్ని డేటాబేస్లోకి తీసుకెళ్తుంది, మరియు docker compose exec miniflux sh మీకు యాప్లో షెల్ ఇస్తుంది.
మీ డేటా వాస్తవానికి ఎక్కడ నిల్వ చేయబడుతుంది
Named volumes కు ప్రాజెక్ట్ ప్రిఫిక్స్ ఉంటుంది, కాబట్టి miniflux అనే డైరెక్టరీలోని db-data అనేది miniflux_db-data గా మారుతుంది:
docker volume ls
docker volume inspect miniflux_db-datainspect అవుట్పుట్ ముఖ్యమైన లైన్ను కలిగి ఉంటుంది:
"Mountpoint": "/var/lib/docker/volumes/miniflux_db-data/_data"ఆ డైరెక్టరీయే డేటాబేస్, ఇది హోస్ట్ ఫైల్సిస్టమ్పై root-owned గా ఉంటుంది మరియు ఇది down, అప్గ్రేడ్లు, మరియు కంటైనర్ రీబిల్డ్ల తర్వాత కూడా అలాగే ఉంటుంది. మీ బ్యాకప్లు ఖచ్చితంగా దేనిని కాపీ చేయాలో అదే ఈ డైరెక్టరీ.
Named volume ను బ్యాకప్ చేయడం
దీనికి ప్రామాణిక పద్ధతి ఏమిటంటే, ఒక తాత్కాలిక (throwaway) కంటైనర్ను ఉపయోగించి, ఆ వాల్యూమ్ను read-only మోడ్లో హోస్ట్ డైరెక్టరీకి మౌంట్ చేసి, tar కమాండ్ ద్వారా ఫైళ్లను కాపీ చేయడం:
docker run --rm \
-v miniflux_db-data:/data:ro \
-v "$PWD":/backup \
alpine:3.22 tar czf /backup/miniflux-db-$(date +%F).tar.gz -C /data .దీనికోసం అదనపు సాఫ్ట్వేర్ ఇన్స్టాల్ చేయనవసరం లేదు, ఏదీ రన్ అవ్వదు. Restore చేసేటప్పుడు కూడా ఇదే పద్ధతిని రివర్స్లో, అంటే tar xzf కమాండ్ను ఉపయోగించి ఖాళీ వాల్యూమ్లోకి డేటాను పంపవచ్చు.
డేటాబేస్ల విషయంలో ఒక ముఖ్యమైన జాగ్రత్త: Postgres డేటా డైరెక్టరీ రన్ అవుతున్నప్పుడు tar చేయడం వల్ల, డేటా మధ్యలో ఆగిపోయిన స్థితిలో (mid-write state) కాపీ అయ్యే ప్రమాదం ఉంది, దీనివల్ల తర్వాత అది సరిగ్గా స్టార్ట్ అవ్వదు. కాబట్టి tar జరిగే కొన్ని సెకన్ల పాటు docker compose stop చేయాలి, లేదా అంతకంటే మంచి పద్ధతి ఏమిటంటే logical dump తీసుకోవడం, ఇది ఎల్లప్పుడూ స్థిరంగా (consistent) ఉంటుంది:
docker compose exec -T db pg_dump -U miniflux miniflux | gzip > miniflux-$(date +%F).sql.gz-T ఫ్లాగ్, Compose డిఫాల్ట్గా కేటాయించే pseudo-terminal ను నిలిపివేస్తుంది; dump అవుట్పుట్ను TTY ద్వారా పంపడం వల్ల అది పాడయ్యే అవకాశం ఉంది. వీటిలో ఒకదానిని cron లో ఉంచి, ఫలితాన్ని VPS నుండి బయటకు కాపీ చేయండి; డేటా ఉన్న అదే డిస్క్లో బ్యాకప్ ఉంచడం అనేది కేవలం కాపీ మాత్రమే, అది అసలైన బ్యాకప్ కాదు. Nextcloud guide లో ఈ రెండు పద్ధతులను ఉపయోగించి పూర్తి స్థాయి షెడ్యూల్డ్ బ్యాకప్ రొటీన్ను ఎలా నిర్మించాలో వివరించబడింది.
వైఫల్య రీతులు మరియు మీరు చూసే సందేశాలు
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock, మీరు ఇంకా docker గ్రూపులో లేరు, లేదా ఉన్నా మీ ప్రస్తుత సెషన్ ఆ మార్పుకు ముందుది. id మీ ప్రభావవంతమైన గ్రూపులను చూపుతుంది; newgrp docker ప్రస్తుత షెల్ను సరిచేస్తుంది, లాగ్ అవుట్ చేసి మళ్ళీ లాగిన్ అవ్వడం ద్వారా అన్ని సెషన్లు సరిచేయబడతాయి.
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?, ఇది వేరే సమస్య: daemon స్వయంగా ఆగిపోయింది. sudo systemctl status docker మరియు sudo journalctl -u docker -n 50 ఎందుకు ఆగిందో చెబుతాయి. VPSలో సాధారణంగా డిస్క్ నిండిపోవడం వల్ల ఇలా జరుగుతుంది, df -h /var/lib/docker ద్వారా దీన్ని తనిఖీ చేయండి.
Bind for 127.0.0.1:8080 failed: port is already allocated, మరొక కంటైనర్ ఇప్పటికే ఆ హోస్ట్ పోర్టును వాడుతోంది. docker ps ఏది వాడుతుందో చూపుతుంది; సాధారణంగా కొన్ని docker run వారాల క్రితం చేసిన ప్రయోగాల వల్ల మిగిలిపోయిన పాత కంటైనర్ దీనికి కారణం. docker ps ఖాళీగా ఉంటే, Docker కాని మరొక ప్రాసెస్ ఆ పోర్టును పట్టుకుని ఉండవచ్చు: sudo ss -tlnp | grep 8080 దాని పేరును చూపుతుంది.
yaml: line 14: did not find expected key, పేర్కొన్న లైన్ వద్ద లేదా దానికి పైన ఇండెంటేషన్ లోపం ఉంది. Compose ఫైళ్లు YAML ఫార్మాట్లో ఉంటాయి: రెండు స్పేసుల ఇండెంటేషన్ ఉండాలి, కేవలం స్పేసులు మాత్రమే వాడాలి, ఎక్కడైనా tab క్యారెక్టర్ ఉంటే అది పనిచేయదు. docker compose config ఏ సేవను ప్రారంభించకుండానే ఫైల్ను ధృవీకరిస్తుంది, ప్రతి మార్పు తర్వాత దీన్ని రన్ చేయడం మంచి అలవాటు.
ufw ఆశ్చర్యం ఎటువంటి ఎర్రర్ చూపదు, అందుకే ఇది ప్రమాదకరం: డిప్లాయ్ విజయవంతమవుతుంది, ufw status అంతా సరిగ్గానే కనిపిస్తుంది, కానీ బయట నుండి పోర్ట్ స్కాన్ చేస్తే మీ డేటాబేస్ కనిపిస్తుంది. పైన ఉన్న ports విభాగాన్ని మళ్ళీ చదవండి, ప్రతి ports: ఎంట్రీలో 127.0.0.1: ప్రిఫిక్స్ ఉందో లేదో తనిఖీ చేయండి, మరియు వేరే మెషీన్ నుండి curl http://your-vps-ip:8080 తో నిర్ధారించుకోండి, connection refused అని వస్తేనే అది సురక్షితం.
ఇక్కడి నుండి, Traefik గైడ్ ఈ సింగిల్ స్టాక్ను ఒకే HTTPS ఎంట్రీ పాయింట్ వెనుక అనేక అప్లికేషన్లుగా మారుస్తుంది, మరియు 2026లో self-host చేయడానికి విలువైనవి అనే జాబితా ద్వారా మీరు మరిన్ని సేవలను రన్ చేయవచ్చు. ఇలాంటి స్టాక్లు కొన్ని రన్ అవుతున్నప్పుడు, ప్రతిదానికీ విడివిడి లాగిన్ ఫారమ్లు కాకుండా, Authentik వంటి self-hosted SSO సర్వర్ ద్వారా వాటన్నింటినీ ఒకే అకౌంట్ కిందకు తీసుకురావచ్చు.
VPSలో Minecraft సర్వర్ వంటి గేమ్ సర్వర్, ప్రాక్టీస్ చేయడానికి ఒక మంచి మొదటి Compose ప్రాజెక్ట్. మీరు ప్రతిరోజూ వాడే దానిపై నేర్చుకోవాలనుకుంటే, openGym, ఒక self-hosted వర్కౌట్ ట్రాకర్ ఒక చిన్న స్టాక్, ఇది ఇమేజ్ ట్యాగ్కు బదులుగా git ట్యాగ్కు పిన్ చేయబడి ఉంటుంది, మరియు మీరు మొదటి పాస్కీని రిజిస్టర్ చేసే ముందు దీనికి TLS అవసరం. సాధారణంగా ప్రజలు ఇతరుల క్లౌడ్ నుండి తమ ఫోటోలను తిరిగి పొందాలనుకుంటారు, కాబట్టి PhotoPrism మరియు Immich ల పోలిక ద్వారా, మీరు వాల్యూమ్ను కేటాయించే ముందే దానికి కావలసిన RAM మరియు బ్యాకప్ పద్ధతులపై అవగాహన వస్తుంది. రెండు సేవలు సరిపోవనిపించినప్పుడు, Notion వంటి AFFiNE వర్క్స్పేస్ను ఏర్పాటు చేయడం నాలుగు కంటైనర్లతో ఇదే పద్ధతులను అనుసరిస్తుంది, ఇది మీరు పైన నేర్చుకున్న పిన్ చేసిన ట్యాగ్లు, హెల్త్చెక్స్ మరియు నేమ్డ్ వాల్యూమ్స్ అలవాటు అయ్యాయో లేదో పరీక్షించడానికి ఒక మంచి మార్గం.
FAQ
Docker daemon socket కి కనెక్ట్ అయ్యేటప్పుడు "permission denied" అని ఎందుకు వస్తుంది?
మీ యూజర్ docker గ్రూప్లో లేరు, లేదా ప్రస్తుత సెషన్ ప్రారంభమైన తర్వాతే మీరు ఆ గ్రూప్లో చేరారు; గ్రూప్ సభ్యత్వం లాగిన్ సమయంలో మాత్రమే వర్తిస్తుంది. sudo usermod -aG docker $USER రన్ చేయండి, ఆపై newgrp docker రన్ చేయండి లేదా లాగ్ అవుట్ చేసి మళ్ళీ లాగిన్ అవ్వండి, ఆపై id తో నిర్ధారించుకోండి. ఈ గ్రూప్ హోస్ట్ సిస్టమ్పై root తో సమానమైన యాక్సెస్ను ఇస్తుంది, కాబట్టి మీరు sudo యాక్సెస్ ఇచ్చే యూజర్లను మాత్రమే ఇందులో చేర్చండి.
docker compose down నా డేటాను తొలగిస్తుందా?
సాధారణ docker compose down డేటాను తొలగించదు, ఇది కేవలం కంటైనర్లను మరియు ప్రాజెక్ట్ నెట్వర్క్ను మాత్రమే తొలగిస్తుంది; named volumes అలాగే ఉంటాయి మరియు తదుపరి up -d వాటిని మళ్ళీ కనెక్ట్ చేస్తుంది. docker compose down -v అనేది డేటాను నాశనం చేసే పద్ధతి: ఇది named volumes ను, అంటే మీ డేటాబేస్ను, ఎటువంటి నిర్ధారణ లేదా వెనక్కి తీసుకునే అవకాశం లేకుండా తొలగిస్తుంది. మీ దగ్గర ధృవీకరించబడిన బ్యాకప్ లేకపోతే, నిజమైన డేటా ఉన్న stack పై ఎప్పుడూ -v రన్ చేయవద్దు.
docker-compose మరియు docker compose మధ్య తేడా ఏమిటి?
docker-compose (హైఫన్) అనేది Compose ను పిలిచే పాత పద్ధతి. పాత సర్వర్లలో ఇది సాధారణంగా Compose v1, అంటే Docker ఇకపై మద్దతు ఇవ్వని Python ఆధారిత పాత వెర్షన్. Docker ఇప్పటికీ ప్రస్తుత Go కోడ్ నుండి నిర్మించిన స్వతంత్ర docker-compose బైనరీని విడుదల చేస్తోంది, కానీ ఆ ఇన్స్టాలేషన్ సిఫార్సు చేయబడదు మరియు కేవలం పాత వెర్షన్ల అనుకూలత కోసం మాత్రమే ఉంచబడింది, కాబట్టి కొత్త సర్వర్లలో దీన్ని వాడకండి. docker compose (స్పేస్) అనేది ప్రస్తుత Compose, ఇది v2 నుండి ప్రారంభమై డిసెంబర్ 2025 నాటికి v5 వెర్షన్లో ఉంది. ఇది Docker CLI కోసం ఒక Go ప్లగ్ఇన్, దీన్ని Docker యొక్క apt రిపోజిటరీ నుండి docker-compose-plugin గా ఇన్స్టాల్ చేస్తారు. కమాండ్లు మరియు YAML ఫైళ్లు దాదాపు పూర్తిగా అనుకూలంగా ఉంటాయి, కాబట్టి పాత ట్యుటోరియల్స్లో docker-compose up అని ఉంటే, మీరు docker compose up అని టైప్ చేయండి.
ufw పోర్ట్ను బ్లాక్ చేసినప్పటికీ, నా Docker కంటైనర్ను ఇంటర్నెట్ నుండి ఎలా యాక్సెస్ చేయగలుగుతున్నాను?
ఎందుకంటే Docker పోర్ట్లను iptables యొక్క PREROUTING చైన్లో DNAT రూల్స్తో పబ్లిష్ చేస్తుంది, మరియు మార్చబడిన ప్యాకెట్లు Docker సొంత చైన్ల ద్వారా FORWARD మార్గంలో ప్రయాణిస్తాయి. ఇవి ufw రూల్స్ వర్తించే INPUT చైన్ను తాకవు. కాబట్టి ufw deny 8080 పబ్లిష్ చేసిన కంటైనర్ పోర్ట్పై ఎటువంటి ప్రభావం చూపదు. దీన్ని మూలంలోనే పరిష్కరించండి: 127.0.0.1: కి మాత్రమే పబ్లిష్ చేయండి మరియు సేవలను రివర్స్ ప్రాక్సీ ద్వారా మాత్రమే ఎక్స్పోజ్ చేయండి.
నేను named volume వాడాలా లేక bind mount వాడాలా?
కంటైనర్ మాత్రమే ఉపయోగించే డేటా కోసం, ముఖ్యంగా డేటాబేస్ల కోసం named volumes వాడండి, ఎందుకంటే ఇమేజ్ ఆశించే ownership మరియు permissions ను Docker స్వయంచాలకంగా సెట్ చేస్తుంది. మీరు హోస్ట్ నుండి కూడా యాక్సెస్ చేసే ఫైళ్ల కోసం bind mounts వాడండి: మీరు ఎడిట్ చేసే కాన్ఫిగరేషన్లు, మీరు అప్లోడ్ చేసే మీడియా, లేదా మీకు పాత్ స్పష్టంగా తెలియాలనుకునే ఏదైనా ఫైల్ కోసం ఇది ఉపయోగపడుతుంది. ఒకవేళ bind mount తో కంటైనర్ ప్రారంభం కాకుండా permission denied ఎర్రర్ వస్తే, హోస్ట్ మరియు కంటైనర్ మధ్య UID సరిపోలకపోవడమే మొదటి కారణం.