[2026] Docker Compose Tutorial for Beginners | Multi-Container Apps Explained
이 글의 핵심
Docker Compose tutorial: services, networks, volumes, depends_on, and env files—run a Node app with MongoDB and Nginx from one docker-compose.yml with clear commands.
Introduction
Docker packages an app and its dependencies into an image; a running image is a container. When you need more than one container—for example a Node API, a database, and optionally Nginx—you can orchestrate them with Docker Compose: one docker-compose.yml and commands like docker compose up -d.
This tutorial explains the mental model (services, networks, volumes) and gives a copy-paste example you can extend. For production-grade health checks and secrets, continue with Docker Compose for Node.js production.
Table of contents
Core concepts
| Concept | Meaning |
|---|---|
| Service | One container spec in Compose: image or build, ports, env, volumes. |
| Project | Default network name is derived from the project folder; all services in the file share it unless you customize networks. |
| Service DNS | Other services resolve mongo, app, etc.—not localhost from one container to another. |
| Volume | Named or bind mount to persist data (e.g. database files) when containers are recreated. |
| depends_on | Start order hint; for ready semantics use health checks (see the production article). |
Dockerfile recap
Compose often builds the API image from a Dockerfile:
아래 코드는 dockerfile를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
Use a .dockerignore to exclude node_modules, .git, .env, and build artifacts.
Your first docker-compose.yml
Example: app + MongoDB + Nginx (reverse proxy). Adjust image tags and env for your project. 다음은 yaml를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# docker-compose.yml
# 실행 예제
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- PORT=3000
- MONGODB_URI=mongodb://mongo:27017/mydb
depends_on:
- mongo
restart: unless-stopped
volumes:
- ./logs:/app/logs
mongo:
image: mongo:7
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- app
restart: unless-stopped
volumes:
mongo-data:
Why mongo:27017 in MONGODB_URI?
mongo is the service name—Docker’s embedded DNS resolves it inside the network.
Daily commands
아래 코드는 bash를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
# Start in background
docker compose up -d
# Follow logs
docker compose logs -f
# Stop and remove containers (volumes kept unless -v)
docker compose down
# Restart services
docker compose restart
# Rebuild images after Dockerfile changes
docker compose up -d --build
Next steps
- Production: add health checks, named volumes for Postgres/Redis, and stricter env handling—Docker Compose for Node.js production.
- Deploy: automate image builds with GitHub Actions CI/CD.
- Edge: terminate TLS and proxy with Nginx reverse proxy.
Conclusion
Compose turns multiple containers into a single declarative stack: same file for teammates, CI, and servers. Master service names, volumes, and up/down, then layer production concerns from the linked guides.