ब्लॉग पर वापस जाएं
अगस्त 19, 2026गाइड

VPS पर Docker Compose से एप्लिकेशन कैसे डिप्लॉय करें

Ubuntu पर Docker Compose v2 की व्यावहारिक उत्पादन गाइड: इंजन इंस्टॉल करें, नेटवर्क और वॉल्यूम वाला Compose फ़ाइल लिखें, सीक्रेट संभालें, आगे रिवर्स प्रॉक्सी रखें, बिना घबराहट रोलआउट से अपडेट करें, और नामित वॉल्यूम बैकअप करें।

VPS पर Docker Compose से एप्लिकेशन कैसे डिप्लॉय करें

Docker Compose एक VPS पर छोटा स्टैक चलाने का आम तरीका है: वेब ऐप, डेटाबेस, Redis कैश, और रिवर्स प्रॉक्सी, एक YAML फ़ाइल में। यह Kubernetes नहीं है। मल्टी-नोड फ़ेलओवर नहीं मिलेगा। दोहराने योग्य, समीक्षा योग्य सेटअप मिलेगा जिसे नए Hiddence VPS पर मिनटों में फिर बना सकते हैं — ज्यादातर साइड प्रोजेक्ट और छोटे उत्पादों को यही चाहिए।

यह लेख मानता है कि शुक्रवार रात docker run से उत्पादन के करीब कुछ चाहिए। हम Docker Engine और Compose प्लगइन इंस्टॉल करेंगे, गैर-root डिप्लॉय उपयोगकर्ता बनाएँगे, हेल्थचेक और रीस्टार्ट नीति वाला Compose फ़ाइल लिखेंगे, सीक्रेट Git से बाहर रखेंगे, इंटरनेट पर केवल रिवर्स-प्रॉक्सी पोर्ट प्रकाशित करेंगे, और अपडेट व बैकअप रूटीन परिभाषित करेंगे। उदाहरण स्टैक सामान्य वेब ऐप प्लस PostgreSQL प्लस Caddy है, लेकिन वही पैटर्न Node, PHP, Python, या वर्कर समूह के लिए काम करता है।

एक VPS पर Compose अभी भी क्यों समझदार है

लोग फैशन के कारण Kubernetes पर कूदते हैं, फिर एक वेबसाइट के लिए सप्ताहांत YAML में बिताते हैं। Compose पठनीय रहता है। फ़ाइल वर्शन करते हैं, पर्यावरण चर दस्तावेज़ करते हैं, और लागू करने से पहले बदलाव diff कर सकते हैं। अलगाव काफ़ी है: नेटवर्क और न्यूनतम-विशेषाधिकार उपयोगकर्ता इस्तेमाल किए हों तो समझौता किया गया ऐप कंटेनर डेटाबेस UNIX सॉकेट न पकड़े। संसाधन सीमा एक मेमोरी लीक को पूरा VPS फ्रीज़ करने से रोकती है।

  • एक फ़ाइल पूरा स्टैक वर्णित करती है
  • नामित वॉल्यूम कंटेनर पुनर्निर्माण से बचते हैं
  • आंतरिक Docker नेटवर्क Postgres को सार्वजनिक इंटरनेट से दूर रखते हैं
  • restart: unless-stopped ज्यादातर रीबूट कवर करता है
  • पहला छोटा पड़ जाए तो दूसरे VPS पर कॉपी आसान

आवश्यकताएँ

ऐप प्लस Postgres के लिए पर्याप्त RAM वाला VPS इस्तेमाल करें। ऐप + डेटाबेस + प्रॉक्सी के लिए यथार्थ न्यूनतम 2 GB प्लान है। Ubuntu 24.04 माना गया है। cgroups पर क्या करता है पढ़े बिना यादृच्छिक Snap से Docker इंस्टॉल न करें; नीचे के चरण Docker के आधिकारिक apt रिपॉजिटरी इस्तेमाल करते हैं।

  • Ubuntu 22.04/24.04, root या sudo
  • 2 GB RAM सुझाया गया (Postgres के बिना बहुत छोटे स्टैक के लिए केवल 1 GB)
  • स्वचालित HTTPS चाहिए तो VPS की ओर इंगित डोमेन
  • सर्वर पर प्रोजेक्ट कॉपी करने का तरीका: Git या अन्य

चरण 1: Docker Engine और Compose v2 इंस्टॉल करें

Compose v2 प्लगइन है जिसे docker compose (स्पेस के साथ) कहा जाता है, पुराना docker-compose Python बाइनरी नहीं। वर्तमान सुरक्षा पैच पाने के लिए दोनों Docker की रिपॉजिटरी से इंस्टॉल करें।

bash
ssh root@YOUR_VPS_IP
apt update && apt -y install ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
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" | tee /etc/apt/sources.list.d/docker.list > /dev/null

apt update
apt -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

docker version
docker compose version

चरण 2: डिप्लॉय उपयोगकर्ता और निर्देशिका लेआउट

Compose को root से चलाना काम करता है, लेकिन docker समूह की सदस्यता वाला समर्पित उपयोगकर्ता साफ है। प्रोजेक्ट /root में नहीं /opt या /srv में रखें ताकि बैकअप और अनुमति स्पष्ट हों। .env वाली निर्देशिका कभी विश्व-लेखनीय न बनाएँ।

bash
adduser --disabled-password --gecos '' deploy
usermod -aG docker deploy
mkdir -p /srv/app
chown deploy:deploy /srv/app
chmod 750 /srv/app

# Log in as deploy for the rest of the file editing:
# su - deploy
# cd /srv/app

चरण 3: उत्पादन-दिमाग वाला Compose फ़ाइल लिखें

नीचे की फ़ाइल टेम्पलेट है। ऐप इमेज अपनी से बदलें। Postgres 0.0.0.0:5432 पर प्रकाशित नहीं होता — केवल Caddy 80 और 443 पर प्रकाशित होता है। हेल्थचेक रिवर्स प्रॉक्सी को अभी डेटाबेस माइग्रेट कर रहे ऐप पर ट्रैफ़िक भेजने से रोकते हैं। इमेज टैग पिन करें; latest आश्चर्य टूटने का तरीका है।

bash
# /srv/app/compose.yaml
services:
  caddy:
    image: caddy:2.8-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      app:
        condition: service_healthy

  app:
    image: ghcr.io/example/webapp:1.4.2
    restart: unless-stopped
    env_file: .env
    environment:
      DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8000/health"]
      interval: 10s
      timeout: 3s
      retries: 10
    networks:
      - frontend
      - backend

  db:
    image: postgres:16-alpine
    restart: unless-stopped
    env_file: .env
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 10
    networks:
      - backend

networks:
  frontend: {}
  backend: {}

volumes:
  pgdata:
  caddy_data:
  caddy_config:

चरण 4: सीक्रेट, .env और Caddyfile

पासवर्ड सर्वर पर .env में रखें, chmod 600 करें, और वह फ़ाइल कभी कमिट न करें। पासवर्ड openssl rand -base64 32 से जनरेट करें। Caddyfile को केवल Docker नेटवर्क पर ऐप सेवा नाम पर रिवर्स प्रॉक्सी करना है।

bash
# /srv/app/.env (permissions 600)
POSTGRES_USER=app
POSTGRES_PASSWORD=change-me-long-random
POSTGRES_DB=app
# plus any APP_SECRET / NEXTAUTH_SECRET your image needs

# /srv/app/Caddyfile
app.example.com {
    encode gzip
    reverse_proxy app:8000
}

chmod 600 /srv/app/.env
cd /srv/app
docker compose up -d
docker compose ps
docker compose logs -f --tail=100

चरण 5: फ़ायरवॉल, लॉग और संसाधन सीमाएँ

UFW को केवल 22, 80 और 443 अनुमति देनी चाहिए। Docker कभी-कभी प्रकाशित पोर्ट के लिए UFW बाईपास करता है; सख्त होस्ट फ़ायरवॉल चाहिए तो अपने Ubuntu संस्करण के लिए वर्तमान Docker + UFW इंटरैक्शन देखें या पोर्ट केवल 127.0.0.1 पर प्रकाशित कर आगे होस्ट Caddy रखें। Postgres VPS न खाए इसके लिए Compose में मेमोरी सीमा सेट करें।

bash
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

# Optional in compose.yaml under app or db:
#    deploy:
#      resources:
#        limits:
#          memory: 512M

# Logs (do not let json-file grow forever):
# { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }
# in /etc/docker/daemon.json then: systemctl restart docker

चरण 6: अपडेट और रोलबैक

काम करने वाला उबाऊ अपडेट: नई इमेज पुल करें, up -d, हेल्थचेक देखें, वापस पिन करने के लिए पिछला टैग git में रखें। ट्रैफ़िक रोकने का इरादा न हो तो उत्पादन डेटाबेस पर docker compose down न करें। down -v वॉल्यूम हटाता है — यह वाइप है, रीस्टार्ट नहीं।

bash
cd /srv/app
git pull   # if the Compose file lives in git

# Change the image tag in compose.yaml, then:
docker compose pull
docker compose up -d
docker compose ps

# Rollback: set the old tag, pull, up -d again
# NEVER: docker compose down -v   # this deletes named volumes

नामित वॉल्यूम बैकअप करें

VPS स्नैपशॉट अच्छा है। दूसरे मशीन पर पुनर्स्थापित करना हो तो तार्किक Postgres डंप बेहतर है। cron से शेड्यूल करें। एक बार पुनर्स्थापना जाँचें, वरना बैकअप नहीं हैं — फ़ाइलें हैं जिनकी आशा है कि बैकअप हैं।

bash
# Postgres dump while the db container is running:
docker compose exec -T db pg_dump -U app app | gzip > /var/backups/app-$(date +%F).sql.gz

# Copy off-box
# scp /var/backups/app-*.sql.gz backup-host:~

# Restore sketch (maintenance window):
# gunzip -c app-2026-08-19.sql.gz | docker compose exec -T db psql -U app app

समस्या निवारण

docker compose ps और docker compose logs service पढ़ें। इमेज पुल विफलताएँ आमतौर पर ghcr/docker hub दर सीमा या लॉगिन के बिना निजी इमेज हैं। Caddy से 502 का अर्थ ऐप स्वस्थ नहीं या प्रॉक्सी होस्टनाम गलत (Caddy कंटेनर के अंदर localhost नहीं Compose सेवा नाम इस्तेमाल करें)। वॉल्यूम पर अनुमति त्रुटियाँ अक्सर मतलब इमेज uid 1000 से चलती है जबकि होस्ट निर्देशिका root है।

  • compose: command not found — पुराना बाइनरी नाम इंस्टॉल किया; docker compose इस्तेमाल करें
  • port is already allocated — कोई और 80/443 का मालिक (Apache, Nginx, दूसरा Caddy)
  • database connection refused — ऐप Postgres तैयार होने से पहले शुरू हुआ; healthcheck + depends_on शर्त इस्तेमाल करें
  • disk full — docker system df, फिर अप्रयुक्त इमेज सावधानी से काटें
  • permission denied on docker.sock — उपयोगकर्ता docker समूह में नहीं, या नया लॉगिन सत्र चाहिए

सुरक्षा

डेटाबेस पोर्ट प्रकाशित न करें। privileged: true न चलाएँ। जानबूझकर कंटेनर मैनेजर न लिख रहे हों तो /var/run/docker.sock ऐप कंटेनर में माउंट न करें। इंजन अपडेट रखें। अपनी इमेज बनाते हों तो स्कैन करें। डिस्क पर .env अभी भी सीक्रेट फ़ाइल है — बॉक्स पर कौन ssh कर सकता है सीमित करें।

  • कोई सार्वजनिक 5432 / 3306 / 6379 नहीं
  • इमेज डाइजेस्ट या कम से कम अपरिवर्तनीय टैग पिन करें
  • chmod 600 .env
  • होस्ट OS के लिए Unattended-upgrades अभी मायने रखते हैं
  • ऐप प्रति एक Compose प्रोजेक्ट विस्फोट त्रिज्या छोटी रखता है

सुझाव

  • compose.yaml git में रखें; वास्तविक सीक्रेट के बिना .env.example रखें
  • वैकल्पिक वर्कर के लिए प्रोफ़ाइल इस्तेमाल करें (docker compose --profile workers up -d)
  • VPS आकार तय करते समय docker stats देखें
  • सोर्स कोड के बाइंड माउंट उत्पादन पैटर्न नहीं — इमेज बेक करें
  • स्टैक कई VPS तक बढ़े तब ऑर्केस्ट्रेशन देखें — उससे पहले नहीं

एक VPS पर उत्पादन-जैसा Compose सेटअप है: आधिकारिक Docker पैकेज, बंद .env, YAML फ़ाइल जो डेटाबेस प्रकाशित नहीं करती, हेल्थचेक, 80/443 पर रिवर्स प्रॉक्सी, UFW, इमेज टैग जिन्हें रोल बैक कर सकते हैं, और Postgres डंप जिन्हें एक बार सचमुच पुनर्स्थापित किया। इस लेख के टेम्पलेट से शुरू करें, ऐप इमेज बदलें, और docker compose down -v को rm -rf जैसी विनाशकारी कमांड का सम्मान दें।