VPS पर Docker Compose से डिप्लॉय करने के लिए Docker Engine और Compose प्लगइन इंस्टॉल करें, प्रोजेक्ट डायरेक्टरी में compose.yaml और .env फ़ाइल रखें, docker compose up -d चलाएँ, और HTTPS के लिए आगे Caddy जैसा रिवर्स प्रॉक्सी लगाएँ। इसके बाद अपडेट बस docker compose pull && docker compose up -d है।
यह गाइड Ubuntu 24.04 या Debian 12 पर एक छोटा लेकिन असली जैसा स्टैक बनाती है: एक वेब ऐप, एक Postgres डेटाबेस और ऑटोमैटिक HTTPS के लिए Caddy।
1. सर्वर तैयार करें
ऐसे सर्वर से शुरुआत करें जिस पर पहले कदम पूरे हो चुके हों: अपडेट, sudo यूज़र, SSH keys और फ़ायरवॉल। इस स्टैक के लिए 2 GB मेमोरी समझदारी भरा न्यूनतम है।
शुरू करने से पहले एक DNS रिकॉर्ड सर्वर की ओर पॉइंट करें, ताकि HTTPS पहली बार में ही काम करे:
app.example.com. A 203.0.113.10 ; example address
app.example.com. AAAA 2001:db8::10 ; example address
2. Docker Engine और Compose इंस्टॉल करें
Docker की अपनी रिपॉज़िटरी इस्तेमाल करें; डिस्ट्रीब्यूशन के पैकेज अक्सर पुराने होते हैं।
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
. /etc/os-release
sudo curl -fsSL "https://download.docker.com/linux/$ID/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/$ID $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
$ID का मान ubuntu या debian होता है, इसलिए यही लाइनें दोनों पर काम करती हैं। जाँचें:
sudo docker run --rm hello-world
docker compose version
अपने यूज़र को बिना sudo के Docker चलाने दें (इसके बाद लॉग आउट करके फिर लॉग इन करें):
sudo usermod -aG docker $USER
docker ग्रुप की सदस्यता असल में रूट एक्सेस के बराबर है। सिर्फ़ भरोसेमंद यूज़र्स को जोड़ें।
शॉर्टकट: Wolkra पर Docker वन-क्लिक ऐप आपके लिए Compose के साथ Docker CE इंस्टॉल कर देता है।
3. प्रोजेक्ट का ढाँचा बनाएँ
mkdir -p ~/apps/myapp && cd ~/apps/myapp
साफ़ ढाँचा महीनों बाद भी सर्वर को समझना आसान बनाता है:
~/apps/myapp/
├── compose.yaml
├── .env # secrets, not in git
└── Caddyfile
4. compose.yaml लिखें
services:
app:
image: ghcr.io/example/myapp:1.4.2
restart: unless-stopped
env_file: .env
environment:
DATABASE_URL: postgres://myapp:${POSTGRES_PASSWORD}@db:5432/myapp
depends_on:
db:
condition: service_healthy
expose:
- "3000"
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: myapp
POSTGRES_DB: myapp
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myapp"]
interval: 10s
retries: 5
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
volumes:
db-data:
caddy-data:
caddy-config:
ध्यान देने लायक बातें:
- इमेज वर्ज़न पिन करें (
1.4.2,16), ताकि रीस्टार्ट पर कभी अचानक कोई बड़ा major अपग्रेड पुल न हो। - ऐप और डेटाबेस के लिए
portsनहीं,expose। वे सिर्फ़ Compose नेटवर्क के अंदर पहुँच में रहते हैं। सिर्फ़ Caddy पोर्ट पब्लिश करता है। - Named volumes कंटेनर दोबारा बनने पर भी डेटा बचाए रखते हैं।
- health check के साथ
depends_onतब तक इंतज़ार करता है जब तक Postgres कनेक्शन स्वीकार करने न लगे।
ghcr.io/example/myapp की जगह अपनी इमेज और पोर्ट डालें।
5. secrets को .env में रखें
cat > .env <<EOF
POSTGRES_PASSWORD=$(openssl rand -hex 24)
APP_SECRET=$(openssl rand -hex 32)
EOF
chmod 600 .env
Compose ${...} substitution के लिए प्रोजेक्ट डायरेक्टरी से .env पढ़ता है, और env_file उसे ऐप तक पहुँचाता है। अगर डायरेक्टरी git checkout है, तो .env को .gitignore में जोड़ें।
6. Caddy से HTTPS जोड़ें
Caddyfile बनाएँ:
app.example.com {
encode zstd gzip
reverse_proxy app:3000
}
DNS के सर्वर की ओर पॉइंट होते ही और पोर्ट 80 व 443 खुले होने पर Caddy अपने-आप सर्टिफ़िकेट ले लेता है और रिन्यू करता है। ज़्यादा विकल्पों के लिए Caddy रिवर्स प्रॉक्सी गाइड देखें।
7. स्टैक शुरू करें
docker compose up -d
docker compose ps
docker compose logs -f caddy
जब Caddy के लॉग में certificate obtained successfully दिखे, तो https://app.example.com खोलें।
8. फ़ायरवॉल का ध्यान रखें
Docker ऐसे iptables नियम डालता है जो UFW से पहले चलते हैं। ports: से पब्लिश किया गया पोर्ट इंटरनेट से पहुँच में रहता है, भले ही UFW कहे कि वह ब्लॉक है। सुरक्षित रहने के तीन तरीके:
- सिर्फ़ रिवर्स प्रॉक्सी पब्लिश करें (जैसा ऊपर किया)।
- बाकी सब कुछ localhost से bind करें:
"127.0.0.1:5432:5432"। - सर्वर के आगे एक क्लाउड फ़ायरवॉल से फ़िल्टर करें, जिसे Docker बायपास नहीं कर सकता। 80 और 443 को कहीं से भी अनुमति दें और 22 को सिर्फ़ अपने पते से।
9. बिना झंझट अपडेट करें
compose.yaml में इमेज टैग बदलें, फिर:
docker compose pull
docker compose up -d
docker image prune -f
Compose सिर्फ़ उन्हीं सर्विसेज़ को दोबारा बनाता है जिनकी इमेज या कॉन्फ़िग बदली है। रोलबैक के लिए पुराना टैग सेट करें और फिर से up -d चलाएँ। बड़े अपग्रेड से पहले स्नैपशॉट लें, जैसे Postgres का नया major वर्ज़न, जिसके लिए dump और restore ज़रूरी है।
10. डेटा का बैकअप लें
वॉल्यूम /var/lib/docker/volumes के अंदर रहते हैं। डेटाबेस के लिए फ़ाइलें कॉपी करने से logical dump ज़्यादा सुरक्षित है:
docker compose exec -T db pg_dump -U myapp myapp | gzip > ~/backups/myapp-$(date +%F).sql.gz
इसे हर रात cron से चलाएँ और फ़ाइलें सर्वर से बाहर कॉपी करें। सर्वर-स्तर के बैकअप भी मदद करते हैं: Wolkra पर दैनिक बैकअप सर्वर कीमत का 20% होते हैं और 7 रिस्टोर पॉइंट रखते हैं। बैकअप रणनीति गाइड सब कुछ एक साथ समझाती है।
11. लॉग और सीमाएँ
Docker के डिफ़ॉल्ट लॉग बिना किसी सीमा के बढ़ते रहते हैं। /etc/docker/daemon.json में उन्हें ग्लोबली सीमित करें:
{
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" }
}
फिर sudo systemctl restart docker चलाएँ। आप mem_limit: 512m से हर सर्विस की मेमोरी भी सीमित कर सकते हैं, ताकि कोई एक कंटेनर बाकी सबके संसाधन न खा जाए।
12. बूट पर अपने-आप शुरू करें
restart: unless-stopped और चालू की गई Docker सर्विस का मतलब है कि रीबूट के बाद स्टैक वापस चालू हो जाता है। एक बार इसे टेस्ट करें:
sudo reboot
# log in again
docker compose -f ~/apps/myapp/compose.yaml ps
13. CI से डिप्लॉय करें
स्टैक चलने लगे तो डिप्लॉय ऑटोमैटिक हो सकते हैं। CI जॉब नए टैग के साथ इमेज बिल्ड और पुश करता है, फिर SSH से सर्वर से कनेक्ट होकर चलाता है:
cd ~/apps/myapp
sed -i 's|myapp:.*|myapp:1.4.3|' compose.yaml
docker compose pull app
docker compose up -d app
CI जॉब को सिर्फ़ इसी सर्वर तक सीमित उसकी अपनी SSH key दें, जैसा SSH keys गाइड में बताया गया है।
एक सर्वर से आगे कब बढ़ें
एक सर्वर पर Compose काफ़ी दूर तक साथ देता है। जब ज़्यादा चाहिए, तो आमतौर पर अगले कदम ये होते हैं:
- डेटाबेस को प्राइवेट नेटवर्क पर उसके अपने सर्वर पर ले जाएँ;
- एक लोड बैलेंसर के पीछे दो ऐप सर्वर चलाएँ;
- डेटा एक ब्लॉक स्टोरेज वॉल्यूम पर रखें जिसे आप सर्वरों के बीच ले जा सकें।
वेब UI से कई ऐप मैनेज करने के लिए Coolify वन-क्लिक ऐप इसी Docker नींव पर बना है। और सुझाव Docker होस्टिंग पर हैं।
अक्सर पूछे जाने वाले सवाल
क्या Docker Compose प्रोडक्शन के लिए काफ़ी है?
एक सर्वर के लिए, हाँ। कई छोटे और मध्यम ऐप सालों तक Compose पर चलते हैं। ऑर्केस्ट्रेटर पर तभी जाएँ जब आपको कई होस्ट, ऑटोमैटिक failover या मशीनों के बीच rolling update चाहिए।
Docker Compose के लिए कितना बड़ा VPS चाहिए?
हर कंटेनर जितना इस्तेमाल करता है, उसे जोड़ें। Postgres और Redis वाला वेब ऐप 2 से 4 GB मेमोरी पर आराम से चलता है; अगर आप सर्वर पर ही इमेज बिल्ड करते हैं, तो उसके लिए जगह छोड़ें।
UFW मेरे कंटेनर पोर्ट को ब्लॉक क्यों नहीं करता?
Docker अपने iptables नियम जोड़ता है जो UFW से पहले चलते हैं। पोर्ट 127.0.0.1 पर पब्लिश करें और आगे रिवर्स प्रॉक्सी लगाएँ, या क्लाउड फ़ायरवॉल से फ़िल्टर करें।
क्या मुझे सर्वर पर ही इमेज बिल्ड करनी चाहिए?
छोटे प्रोजेक्ट के लिए यह चलता है। दोहराए जा सकने वाले डिप्लॉय के लिए CI में बिल्ड करें, रजिस्ट्री में पुश करें और सर्वर पर सिर्फ़ पुल करें।
क्या मैं Docker खुद इंस्टॉल करना छोड़ सकता हूँ?
हाँ। Wolkra पर सर्वर बनाते समय Docker CE वन-क्लिक ऐप चुनें; इसमें Docker और Compose प्लगइन पहले से इंस्टॉल आते हैं।