विकास के लिए डॉकर कंपोज़: स्थानीय अवसंरचना
एक सुखद ऑनबोर्डिंग अनुभव ("क्लोन और रन pnpm dev:infra") और एक दर्दनाक अनुभव ("पहले PostgreSQL सेट करें, फिर Redis कॉन्फ़िगर करें, फिर...") के बीच का अंतर इस बात पर निर्भर करता है कि आपका डॉकर कंपोज़ सेटअप आपकी बुनियादी ढांचे की आवश्यकताओं को कितनी अच्छी तरह से पकड़ता है। एक अच्छी तरह से तैयार किया गया docker-compose.dev.yml किसी भी मशीन पर किसी भी डेवलपर को मिनटों में बिल्कुल वही बुनियादी ढांचा चलाने की सुविधा देता है।
यह मार्गदर्शिका उत्पादन-गुणवत्ता वाले स्थानीय विकास स्टैक के पैटर्न को कवर करती है: सेवा कॉन्फ़िगरेशन, स्वास्थ्य जांच, नेटवर्किंग, वॉल्यूम प्रबंधन, और आपके एप्लिकेशन के स्टार्टअप अनुक्रम के साथ एकीकरण।
मुख्य बातें
- सिस्टम इंस्टॉलेशन के साथ टकराव से बचने के लिए स्थानीय रूप से PostgreSQL (5433) के लिए एक गैर-डिफ़ॉल्ट पोर्ट का उपयोग करें
- सेवा निर्भरता पर स्वास्थ्य जांच "कनेक्शन अस्वीकृत" स्टार्टअप त्रुटियों को रोकती है
- नामित वॉल्यूम कंटेनर पुनरारंभ के बीच डेटाबेस डेटा को बनाए रखते हैं - बाइंड माउंट विंडोज़ पर विश्वसनीय रूप से काम नहीं करते हैं
- अपनी
.env.localफ़ाइल से पर्यावरण चर को कंटेनर में लोड करने के लिएenv_fileका उपयोग करेंdocker-compose.dev.ymlकोdocker-compose.prod.ymlसे अलग करें - वे विभिन्न उद्देश्यों की पूर्ति करते हैंdepends_on.condition: service_healthyपैटर्न केवल कंटेनर प्रारंभ की नहीं, बल्कि वास्तविक तत्परता की प्रतीक्षा करता है- वैकल्पिक सेवाओं (ईमेल, मॉनिटरिंग) को ऑप्ट-इन करने के लिए
profilesका उपयोग करेंdocker compose(v2) चलाएँ,docker-compose(v1) नहीं - प्लगइन सिंटैक्स चालू है
संपूर्ण विकास ढेर
# infrastructure/docker-compose.dev.yml
name: ecosire-dev
services:
# ─── PostgreSQL ─────────────────────────────────────────────────
postgres:
image: postgres:17-alpine
container_name: ecosire-postgres
environment:
POSTGRES_DB: ecosire_dev
POSTGRES_USER: ecosire
POSTGRES_PASSWORD: dev_password_change_in_prod
ports:
- "5433:5432" # 5433 externally — avoids conflicts with system PostgreSQL
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init-scripts:/docker-entrypoint-initdb.d # Run SQL on first start
command: >
postgres
-c shared_buffers=256MB
-c effective_cache_size=1GB
-c work_mem=16MB
-c maintenance_work_mem=128MB
-c checkpoint_completion_target=0.9
-c wal_buffers=16MB
-c max_connections=100
-c log_min_duration_statement=100
-c log_statement=ddl
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ecosire -d ecosire_dev"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
restart: unless-stopped
# ─── Redis ──────────────────────────────────────────────────────
redis:
image: redis:7-alpine
container_name: ecosire-redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: >
redis-server
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--appendonly yes
--appendfsync everysec
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
# ─── Authentik (Identity Provider) ──────────────────────────────
authentik-server:
image: ghcr.io/goauthentik/server:2024.12
container_name: ecosire-authentik
command: server
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgres
AUTHENTIK_POSTGRESQL__USER: ecosire
AUTHENTIK_POSTGRESQL__PASSWORD: dev_password_change_in_prod
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_SECRET_KEY: dev-secret-key-change-in-production-32chars
AUTHENTIK_ERROR_REPORTING__ENABLED: "false"
AUTHENTIK_DISABLE_STARTUP_ANALYTICS: "true"
volumes:
- authentik_media:/media
- authentik_certs:/certs
ports:
- "9000:9000" # HTTP
- "9443:9443" # HTTPS
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "ak healthcheck"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s # Authentik takes time to initialize
restart: unless-stopped
authentik-worker:
image: ghcr.io/goauthentik/server:2024.12
container_name: ecosire-authentik-worker
command: worker
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgres
AUTHENTIK_POSTGRESQL__USER: ecosire
AUTHENTIK_POSTGRESQL__PASSWORD: dev_password_change_in_prod
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_SECRET_KEY: dev-secret-key-change-in-production-32chars
volumes:
- authentik_media:/media
- authentik_certs:/certs
- /var/run/docker.sock:/var/run/docker.sock # For Authentik's proxy
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
# ─── Mailpit (Email Testing) ─────────────────────────────────────
mailpit:
image: axllent/mailpit:latest
container_name: ecosire-mailpit
ports:
- "1025:1025" # SMTP
- "8025:8025" # Web UI
environment:
MP_MAX_MESSAGES: 200
MP_SMTP_AUTH_ACCEPT_ANY: true
MP_SMTP_AUTH_ALLOW_INSECURE: true
restart: unless-stopped
profiles:
- email # Optional — use `docker compose --profile email up`
# ─── pgAdmin (Database GUI) ─────────────────────────────────────
pgadmin:
image: dpage/pgadmin4:latest
container_name: ecosire-pgadmin
environment:
PGADMIN_DEFAULT_EMAIL: [email protected]
PGADMIN_DEFAULT_PASSWORD: admin
PGADMIN_CONFIG_SERVER_MODE: "False"
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: "False"
ports:
- "5050:80"
volumes:
- pgadmin_data:/var/lib/pgadmin
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped
profiles:
- tools # Optional
networks:
default:
name: ecosire-dev-network
volumes:
postgres_data:
name: ecosire-postgres-data
redis_data:
name: ecosire-redis-data
authentik_media:
name: ecosire-authentik-media
authentik_certs:
name: ecosire-authentik-certs
pgadmin_data:
name: ecosire-pgadmin-data
पैकेज.जेसन स्क्रिप्ट्स
डॉकर कंपोज़ कमांड को अपनी मोनोरेपो स्क्रिप्ट में वायर करें:
{
"scripts": {
"dev:infra": "docker compose -f infrastructure/docker-compose.dev.yml up -d",
"dev:infra:down": "docker compose -f infrastructure/docker-compose.dev.yml down",
"dev:infra:logs": "docker compose -f infrastructure/docker-compose.dev.yml logs -f",
"dev:infra:reset": "docker compose -f infrastructure/docker-compose.dev.yml down -v && pnpm dev:infra",
"dev:infra:email": "docker compose -f infrastructure/docker-compose.dev.yml --profile email up -d",
"dev:infra:tools": "docker compose -f infrastructure/docker-compose.dev.yml --profile tools up -d"
}
}
--profile ध्वज वैकल्पिक सेवाओं (मेलपिट के साथ ईमेल परीक्षण, पीजीएडमिन के साथ डेटाबेस जीयूआई) को स्पष्ट रूप से अनुरोध किए जाने तक निष्क्रिय रहने देता है।
डेटाबेस आरंभीकरण स्क्रिप्ट
SQL फ़ाइलों को infrastructure/init-scripts/ में रखें - वे पहले कंटेनर प्रारंभ पर चलते हैं:
-- infrastructure/init-scripts/01-create-databases.sql
-- Create all databases Authentik needs separately from the app DB
CREATE DATABASE authentik;
GRANT ALL PRIVILEGES ON DATABASE authentik TO ecosire;
-- Create test database for CI
CREATE DATABASE ecosire_test;
GRANT ALL PRIVILEGES ON DATABASE ecosire_test TO ecosire;
-- infrastructure/init-scripts/02-extensions.sql
-- Enable PostgreSQL extensions
\c ecosire_dev;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- Trigram search
CREATE EXTENSION IF NOT EXISTS "btree_gin"; -- Composite GIN indexes
\c ecosire_test;
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
आरंभीकरण स्क्रिप्ट वर्णमाला क्रम में चलती हैं। \c database_name psql मेटाकमांड सक्रिय डेटाबेस को स्विच करता है।
पर्यावरण चर एकीकरण
आपका एप्लिकेशन मोनोरेपो रूट में .env.local से पढ़ता है। डॉकर सेवाओं को यह जानना आवश्यक है कि सेवा नामों का उपयोग करके एक-दूसरे से कैसे जुड़ा जाए (localhost नहीं):
# .env.local (monorepo root)
# PostgreSQL — use 5433 externally (host) or 5432 internally (container network)
DATABASE_URL=postgresql://ecosire:dev_password_change_in_prod@localhost:5433/ecosire_dev
# Redis
REDIS_URL=redis://localhost:6379
# Authentik — use 9000 for external calls from your dev machine
AUTHENTIK_URL=http://localhost:9000
# Use service name for server-to-server calls within Docker network
AUTHENTIK_INTERNAL_URL=http://authentik-server:9000
# Email (Mailpit SMTP)
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_SECURE=false
# Application
NODE_ENV=development
डॉकर के अंदर चल रहे एप्लिकेशन के लिए जिन्हें अन्य सेवाओं से बात करने की आवश्यकता है, सेवा नामों का उपयोग करें। आपके होस्ट मशीन (डेव मोड में NestJS, Next.js) पर चलने वाले एप्लिकेशन के लिए, होस्ट-मैप किए गए पोर्ट के साथ localhost का उपयोग करें।
स्वास्थ्य जांच गहन गोता
स्वास्थ्य जांच व्यापक स्टार्टअप विफलताओं को रोकती है। depends_on.condition: service_healthy वास्तविक तैयारी की प्रतीक्षा करता है, न कि केवल कंटेनर प्रारंभ की:
# Without health checks — can fail because PostgreSQL isn't ready
depends_on:
- postgres
# With health checks — waits for PostgreSQL to accept connections
depends_on:
postgres:
condition: service_healthy
आपकी अपनी सेवाओं के लिए कस्टम स्वास्थ्य जांच:
// apps/api/src/health/health.controller.ts
@Get()
@Public()
@HealthCheck()
async check() {
return this.health.check([
() => this.db.isHealthy('database'),
() => this.redis.isHealthy('redis'),
]);
}
# If your API is also dockerized
api:
image: ecosire-api:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
वॉल्यूम प्रबंधन
नामित वॉल्यूम पुनरारंभ के बीच डेटा बनाए रखते हैं। समझें कि प्रत्येक वॉल्यूम प्रकार का उपयोग कब करना है:
| प्रकार | दृढ़ता | प्रदर्शन | के लिए उपयोग करें |
|---|---|---|---|
| नामित मात्रा | हाँ | उत्कृष्ट | डेटाबेस डेटा |
| बाइंड माउंट | हाँ | अच्छा (लिनक्स), ख़राब (मैकओएस) | स्रोत कोड हॉट-रीलोड |
| tmpfs | नहीं | उत्कृष्ट | अस्थायी फ़ाइलें, रहस्य |
# Use bind mounts for source code (enables hot reload)
volumes:
- ./apps/api/src:/app/src # Code changes reflected immediately
# Use named volumes for data
volumes:
- postgres_data:/var/lib/postgresql/data
# Use tmpfs for ephemeral data
volumes:
- type: tmpfs
target: /tmp
डॉकर डेस्कटॉप के साथ macOS पर, बाइंड माउंट्स gRPC FUSE का उपयोग करते हैं जो लिनक्स की तुलना में काफी धीमा है। NestJS और Next.js डेव सर्वर के लिए, मूल फ़ाइल सिस्टम प्रदर्शन प्राप्त करने के लिए उन्हें सीधे अपने होस्ट मशीन पर चलाएं (डॉकर में नहीं)।
प्रोडक्शन डॉकर कंपोज़
उत्पादन कंपोज़ फ़ाइल संरचनात्मक रूप से भिन्न है - कोई स्थानीय पोर्ट नहीं, पुनरारंभ नीतियां, उत्पादन संसाधन सीमाएँ:
# infrastructure/docker-compose.prod.yml
name: ecosire-prod
services:
postgres:
image: postgres:17-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
# No port mapping — only accessible within Docker network
restart: always
deploy:
resources:
limits:
memory: 2G
reservations:
memory: 512M
redis:
image: redis:7-alpine
command: redis-server --requirepass ${REDIS_PASSWORD} --maxmemory 1gb
volumes:
- redis_data:/data
restart: always
# No port mapping — internal only
volumes:
postgres_data:
redis_data:
उत्पादन बाहरी रूप से बंदरगाहों को उजागर नहीं करता है - एप्लिकेशन आंतरिक डॉकर नेटवर्क के माध्यम से जुड़ते हैं। Nginx बाहरी ट्रैफ़िक को संभालता है।
सामान्य नुकसान और समाधान
नुकसान 1: सिस्टम सेवाओं के साथ पोर्ट का टकराव
PostgreSQL, Redis और अन्य सेवाएँ अक्सर सिस्टम सेवाओं के रूप में चलती हैं। विकास में हमेशा गैर-मानक बंदरगाहों पर मैप करें:
- PostgreSQL:
5433:5432(5432:5432नहीं) - रेडिस:
6379:6379रखें (शायद ही कभी टकराव) - डिफ़ॉल्ट पोर्ट का उपयोग क्या कर रहा है यह जांचने के लिए
lsof -i :5432चलाएँ
नुकसान 2: Linux पर वॉल्यूम अनुमति संबंधी समस्याएँ
लिनक्स पर डॉकर वॉल्यूम डिफ़ॉल्ट रूप से रूट स्वामित्व का उपयोग करते हैं। यदि आपका कंटेनर उपयोगकर्ता गैर-रूट है, तो सही स्वामित्व सेट करें:
postgres:
image: postgres:17-alpine
user: "999:999" # postgres user's UID:GID
# Or use init container to fix permissions
नुकसान 3: प्रामाणिक आरंभीकरण में 60+ सेकंड लगते हैं
ऑथेंटिक पहली शुरुआत में डेटाबेस माइग्रेशन चलाता है। स्वास्थ्य जांच में start_period: 60s इसे समय देता है। यदि ऑथेंटिक तैयार होने से पहले आश्रित सेवाएँ शुरू हो जाती हैं, तो वे विफल हो जाएँगी। service_healthy शर्त का उपयोग करें और इसे पर्याप्त start_period दें।
नुकसान 4: मैक पर डॉकर डेस्कटॉप संसाधन सीमा
डिफ़ॉल्ट डॉकर डेस्कटॉप 2 सीपीयू और 2 जीबी रैम आवंटित करता है - पोस्टग्रेएसक्यूएल + रेडिस + ऑथेंटिक को एक साथ चलाने के लिए पर्याप्त नहीं है। डॉकर डेस्कटॉप सेटिंग्स> संसाधनों में कम से कम 4 सीपीयू और 6 जीबी रैम तक वृद्धि।
नुकसान 5: docker-compose बनाम docker compose
पुराना docker-compose (v1, पायथन में लिखा गया) अप्रचलित है। docker compose (v2, प्लगइन) का उपयोग करें। अपना संस्करण जांचें: docker compose version। यदि आपको Docker Compose version v2.x.x दिखाई देता है, तो आप v2 का उपयोग कर रहे हैं।
अक्सर पूछे जाने वाले प्रश्न
क्या मुझे विकास के दौरान डॉकर में अपनी एप्लिकेशन सेवाएं (NestJS, Next.js) चलानी चाहिए?
आम तौर पर नहीं - सक्रिय विकास के लिए, तेज़ हॉट-रीलोड और आसान डिबगिंग के लिए अपनी एप्लिकेशन सेवाओं को अपने होस्ट मशीन पर चलाएं। डॉकर का उपयोग केवल बुनियादी सुविधाओं (डेटाबेस, कैश, पहचान प्रदाता) के लिए करें जो स्थिर हैं और जिन्हें बार-बार पुनरारंभ करने की आवश्यकता नहीं है। अपवाद यह है कि यदि आपके एप्लिकेशन में मूल निर्भरताएं हैं जो आपके विकास ओएस और उत्पादन वातावरण के बीच भिन्न हैं।
मैं डॉकर कंपोज़ वर्कफ़्लो में डेटाबेस माइग्रेशन को कैसे प्रबंधित करूं?
इन्फ्रास्ट्रक्चर शुरू करने के बाद अपनी होस्ट मशीन से माइग्रेशन चलाएँ: pnpm dev:infra && pnpm db:migrate। विकास के दौरान डॉकर कंटेनर के अंदर माइग्रेशन न चलाएं - आप प्रकार की जांच और आईडीई एकीकरण खो देते हैं जो ड्रिज़ल माइग्रेशन को सुरक्षित बनाता है। प्रारंभिक डेटाबेस निर्माण के लिए, डॉकर की initdb.d स्क्रिप्ट का उपयोग करें।
मैं अपने स्थानीय डॉकर वॉल्यूम का बैकअप और पुनर्स्थापित कैसे करूं?
बैकअप लेने के लिए docker run --rm -v postgres_data:/data -v $(pwd):/backup alpine tar czf /backup/postgres-backup.tar.gz /data का उपयोग करें। tar xzf का उपयोग करके उसी दृष्टिकोण से पुनर्स्थापित करें। विकास के लिए, आप pg_dump के साथ डंप भी कर सकते हैं और psql के साथ पुनर्स्थापित कर सकते हैं क्योंकि आपके पास पोर्ट खुला है।
मैं डॉकर कंपोज़ स्थिति को टीम के अन्य सदस्यों के साथ कैसे साझा करूं?
डॉकर कंपोज़ फ़ाइल git के माध्यम से साझा की जाती है, लेकिन वॉल्यूम में डेटा स्थानीय है। प्रत्येक डेवलपर एक खाली डेटाबेस से शुरू करता है और इसे भरने के लिए माइग्रेशन/बीज चलाता है। सुसंगत परीक्षण डेटा बनाने के लिए बीज स्क्रिप्ट (रेपो के लिए प्रतिबद्ध) का उपयोग करें। साझा docker-compose.dev.yml सुनिश्चित करता है कि हर कोई समान सेवा संस्करण और कॉन्फ़िगरेशन का उपयोग करता है।
विकास में वास्तविक ईमेल के बजाय मेलपिट का उपयोग क्यों करें?
मेलपिट एक स्थानीय एसएमटीपी सर्वर है जो सभी आउटगोइंग ईमेल को कैप्चर करता है और उन्हें देखने के लिए एक वेब यूआई प्रदान करता है। यह विकास के दौरान वास्तविक उपयोगकर्ताओं को गलती से वास्तविक ईमेल भेजने से रोकता है, एसएमटीपी क्रेडेंशियल्स की आवश्यकता नहीं होती है, और आपको अपने इनबॉक्स की जांच किए बिना ईमेल टेम्पलेट्स को सत्यापित करने देता है। SMTP_HOST=localhost SMTP_PORT=1025 का उपयोग करने के लिए अपने ऐप को कॉन्फ़िगर करें और कैप्चर किए गए ईमेल देखने के लिए http://localhost:8025 पर जाएं।
अगले चरण
स्थानीय विकास के लिए एक अच्छी तरह से तैयार किया गया डॉकर कंपोज़ सेटअप एक निवेश है जो हर बार एक नए डेवलपर के शामिल होने या आपके द्वारा एक नई मशीन तैयार करने पर लाभांश का भुगतान करता है। ECOSIRE पूरी टीम में स्थानीय विकास के लिए डॉकर कंपोज़ में PostgreSQL 17, Redis 7 और ऑथेंटिक चलाता है।
क्या आपको अपने स्थानीय विकास बुनियादी ढांचे को डिजाइन करने या उत्पादन के लिए अपने एप्लिकेशन को कंटेनरीकृत करने में सहायता की आवश्यकता है? हमारी DevOps सेवाओं का अन्वेषण करें यह देखने के लिए कि हम कैसे मदद कर सकते हैं।
लेखक
ECOSIRE Research and Development Team
ECOSIRE में एंटरप्राइज़-ग्रेड डिजिटल उत्पाद बना रहे हैं। Odoo एकीकरण, ई-कॉमर्स ऑटोमेशन, और AI-संचालित व्यावसायिक समाधानों पर अंतर्दृष्टि साझा कर रहे हैं।
संबंधित लेख
AWS EC2 Deployment Guide for Web Applications
Complete AWS EC2 deployment guide: instance selection, security groups, Node.js deployment, Nginx reverse proxy, SSL, auto-scaling, CloudWatch monitoring, and cost optimization.
Cloud vs On-Premise ERP in 2026: The Definitive Guide
Cloud vs on-premise ERP in 2026: total cost analysis, security comparison, scalability, compliance, and the right deployment model for your business.
Building Custom Odoo Modules: Developer Tutorial
Step-by-step tutorial for building custom Odoo 19 modules. Covers module structure, models, views, security, wizards, and best practices for production-ready code.