Docker Compose lets you define and run multi-container apps (app server + database + Redis + etc.) with a single command. This guide covers writing a compose file, common service patterns, and production tips.
In this guide
Create docker-compose.yml: services: — app: — build: . — ports: ["3000:3000"] — env_file: .env.local — depends_on: [db] — db: — image: postgres:16-alpine — environment: POSTGRES_DB: mydb POSTGRES_USER: myuser POSTGRES_PASSWORD: secret — volumes: [pgdata:/var/lib/postgresql/data] — volumes: pgdata:. Run everything: docker compose up -d. Stop: docker compose down.
Add to services: redis: — image: redis:7-alpine — command: redis-server --appendonly yes — volumes: [redisdata:/data]. Connect from your app using the service name as hostname: REDIS_URL=redis://redis:6379. Docker Compose creates a private network — services can reach each other by service name. No need to expose Redis port to the host unless you need external access.
Create .env (committed, contains non-secret defaults) and .env.local (gitignored, contains secrets). Reference in compose: env_file: [.env, .env.local]. Or use env_file: .env.local on the specific service. Variables in the later file override earlier ones. Never hardcode secrets in docker-compose.yml — it may end up in version control. Use .env for COMPOSE_PROJECT_NAME and port defaults.
docker compose up -d — start all services detached. docker compose down — stop and remove containers (data persists in volumes). docker compose down -v — stop and remove containers AND volumes (data deleted). docker compose logs app -f — stream logs for the app service. docker compose exec app sh — open a shell in the running app container. docker compose ps — show status of all services. docker compose restart app — restart one service without touching others.
Create docker-compose.override.yml for development overrides — Docker Compose automatically merges it with docker-compose.yml. In override: add volume mounts for live code reloading (- ./src:/app/src), change the command to npm run dev, and expose extra debug ports. In production, use docker-compose.prod.yml and run: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d. This keeps environments separate without duplicating config.
Need Help?
Our engineering team handles implementations like this every week. Get a free scoping call — we will tell you exactly what it takes and what it costs.
Book a free callCompetitive Intelligence
Efficiency Modeling
© 2026 NexWorldTech — Built for Global Dominance.