Docker Compose
Docker Compose¶
1. Docker Compose๋?¶
Docker Compose๋ ์ฌ๋ฌ ์ปจํ ์ด๋๋ฅผ ์ ์ํ๊ณ ์คํํ๋ ๋๊ตฌ์ ๋๋ค. YAML ํ์ผ ํ๋๋ก ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์คํ์ ๊ด๋ฆฌํฉ๋๋ค.
์ Docker Compose๋ฅผ ์ฌ์ฉํ ๊น์?¶
์ผ๋ฐ Docker ๋ช ๋ น์ด:
# ๋คํธ์ํฌ ์์ฑ
docker network create myapp-network
# ๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํ
docker run -d \
--name db \
--network myapp-network \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:15
# ๋ฐฑ์๋ ์คํ
docker run -d \
--name backend \
--network myapp-network \
-e DATABASE_URL=postgres://... \
-p 3000:3000 \
my-backend
# ํ๋ก ํธ์๋ ์คํ
docker run -d \
--name frontend \
--network myapp-network \
-p 80:80 \
my-frontend
Docker Compose:
docker compose up -d
| ์ฅ์ | ์ค๋ช |
|---|---|
| ๊ฐํธํจ | ํ ๋ช ๋ น์ผ๋ก ์ ์ฒด ์คํ |
| ์ ์ธ์ | YAML๋ก ๋ช ํํ๊ฒ ์ ์ |
| ๋ฒ์ ๊ด๋ฆฌ | ์ค์ ํ์ผ์ Git์ผ๋ก ๊ด๋ฆฌ |
| ์ฌํ์ฑ | ๋์ผํ ํ๊ฒฝ ์ฌํ ๊ฐ๋ฅ |
2. ์ค์น ํ์ธ¶
Docker Desktop์๋ Docker Compose๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
# ๋ฒ์ ํ์ธ
docker compose version
# Docker Compose version v2.23.0
# ๋๋ (๊ตฌ๋ฒ์ )
docker-compose --version
์ฐธ๊ณ :
docker-compose(ํ์ดํ)์ ๊ตฌ๋ฒ์ ,docker compose(๊ณต๋ฐฑ)์ ์ ๋ฒ์ ์ ๋๋ค.
3. docker-compose.yml ๊ธฐ๋ณธ ๊ตฌ์กฐ¶
# docker-compose.yml
services:
์๋น์ค๋ช
1:
image: ์ด๋ฏธ์ง๋ช
ports:
- "ํธ์คํธ:์ปจํ
์ด๋"
environment:
- ๋ณ์=๊ฐ
volumes:
- ๋ณผ๋ฅจ:๊ฒฝ๋ก
depends_on:
- ๋ค๋ฅธ์๋น์ค
์๋น์ค๋ช
2:
build: ./๊ฒฝ๋ก
...
volumes:
๋ณผ๋ฅจ๋ช
:
networks:
๋คํธ์ํฌ๋ช
:
4. ์ฃผ์ ์ค์ ์ต์ ¶
services - ์๋น์ค ์ ์¶
services:
web:
image: nginx:alpine
image - ์ด๋ฏธ์ง ์ง์ ¶
services:
db:
image: postgres:15
redis:
image: redis:7-alpine
build - Dockerfile๋ก ๋น๋¶
services:
app:
build: . # ํ์ฌ ๋๋ ํ ๋ฆฌ์ Dockerfile
api:
build:
context: ./backend # ๋น๋ ์ปจํ
์คํธ
dockerfile: Dockerfile # Dockerfile ๊ฒฝ๋ก
args: # ๋น๋ ์ธ์
- NODE_ENV=production
ports - ํฌํธ ๋งคํ¶
services:
web:
ports:
- "8080:80" # ํธ์คํธ:์ปจํ
์ด๋
- "443:443"
api:
ports:
- "3000:3000"
environment - ํ๊ฒฝ ๋ณ์¶
services:
db:
environment:
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=secret
- POSTGRES_DB=myapp
# ๋๋ key: value ํ์
api:
environment:
NODE_ENV: production
DB_HOST: db
env_file - ํ๊ฒฝ ๋ณ์ ํ์ผ¶
services:
api:
env_file:
- .env
- .env.local
.env ํ์ผ:
DB_HOST=localhost
DB_PASSWORD=secret
API_KEY=abc123
volumes - ๋ณผ๋ฅจ ๋ง์ดํธ¶
services:
db:
volumes:
- pgdata:/var/lib/postgresql/data # Named volume
- ./init.sql:/docker-entrypoint-initdb.d/init.sql # ๋ฐ์ธ๋ ๋ง์ดํธ
app:
volumes:
- ./src:/app/src # ์์ค ์ฝ๋ ๋ง์ดํธ (๊ฐ๋ฐ์ฉ)
- /app/node_modules # ์ต๋ช
๋ณผ๋ฅจ (๋ฎ์ด์ฐ๊ธฐ ๋ฐฉ์ง)
volumes:
pgdata: # Named volume ์ ์ธ
depends_on - ์์กด์ฑ¶
services:
api:
depends_on:
- db
- redis
db:
image: postgres:15
redis:
image: redis:7
์ฃผ์:
depends_on์ ์์ ์์๋ง ๋ณด์ฅํฉ๋๋ค. ์๋น์ค๊ฐ "์ค๋น"๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์์ต๋๋ค.
networks - ๋คํธ์ํฌ¶
services:
frontend:
networks:
- frontend-net
backend:
networks:
- frontend-net
- backend-net
db:
networks:
- backend-net
networks:
frontend-net:
backend-net:
restart - ์ฌ์์ ์ ์ฑ ¶
services:
web:
restart: always # ํญ์ ์ฌ์์
api:
restart: unless-stopped # ์๋ ์ค์ง ์ ๊น์ง ์ฌ์์
worker:
restart: on-failure # ์คํจ ์ ์ฌ์์
healthcheck - ํฌ์ค์ฒดํฌ¶
services:
api:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
5. Docker Compose ๋ช ๋ น์ด¶
์คํ¶
# ์คํ (ํฌ๊ทธ๋ผ์ด๋)
docker compose up
# ๋ฐฑ๊ทธ๋ผ์ด๋ ์คํ
docker compose up -d
# ์ด๋ฏธ์ง ์ฌ๋น๋ ํ ์คํ
docker compose up --build
# ํน์ ์๋น์ค๋ง ์คํ
docker compose up -d web api
์ค์ง/์ญ์ ¶
# ์ค์ง
docker compose stop
# ์ค์ง ๋ฐ ์ปจํ
์ด๋ ์ญ์
docker compose down
# ๋ณผ๋ฅจ๋ ํจ๊ป ์ญ์
docker compose down -v
# ์ด๋ฏธ์ง๋ ํจ๊ป ์ญ์
docker compose down --rmi all
์ํ ํ์ธ¶
# ์๋น์ค ๋ชฉ๋ก
docker compose ps
# ๋ก๊ทธ ํ์ธ
docker compose logs
# ํน์ ์๋น์ค ๋ก๊ทธ
docker compose logs api
# ์ค์๊ฐ ๋ก๊ทธ
docker compose logs -f
์๋น์ค ๊ด๋ฆฌ¶
# ์ฌ์์
docker compose restart
# ํน์ ์๋น์ค ์ฌ์์
docker compose restart api
# ์๋น์ค ์ค์ผ์ผ๋ง
docker compose up -d --scale api=3
# ์๋น์ค ๋ด ๋ช
๋ น ์คํ
docker compose exec api bash
docker compose exec db psql -U postgres
6. ์ค์ต ์์ ¶
์์ 1: ์น + ๋ฐ์ดํฐ๋ฒ ์ด์ค¶
ํ๋ก์ ํธ ๊ตฌ์กฐ:
my-webapp/
โโโ docker-compose.yml
โโโ .env
โโโ app/
โโโ Dockerfile
โโโ index.js
docker-compose.yml:
services:
app:
build: ./app
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb
depends_on:
- db
db:
image: postgres:15-alpine
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
- POSTGRES_DB=mydb
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
pgdata:
app/Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
app/index.js:
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.json({
message: 'Hello from Docker Compose!',
db_url: process.env.DATABASE_URL ? 'Connected' : 'Not set'
});
});
app.listen(3000, () => console.log('Server on port 3000'));
์คํ:
cd my-webapp
docker compose up -d
curl http://localhost:3000
docker compose logs -f
docker compose down
์์ 2: ํ์คํ ์ ํ๋ฆฌ์ผ์ด์ ¶
# docker-compose.yml
services:
# ํ๋ก ํธ์๋ (React)
frontend:
build: ./frontend
ports:
- "80:80"
depends_on:
- backend
# ๋ฐฑ์๋ (Node.js)
backend:
build: ./backend
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=db
- DB_NAME=myapp
- REDIS_HOST=redis
depends_on:
- db
- redis
# ๋ฐ์ดํฐ๋ฒ ์ด์ค (PostgreSQL)
db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
# ์บ์ (Redis)
redis:
image: redis:7-alpine
volumes:
- redisdata:/data
# ๊ด๋ฆฌ ๋๊ตฌ (pgAdmin)
pgadmin:
image: dpage/pgadmin4
environment:
- PGADMIN_DEFAULT_EMAIL=admin@example.com
- PGADMIN_DEFAULT_PASSWORD=admin
ports:
- "5050:80"
depends_on:
- db
volumes:
pgdata:
redisdata:
.env:
DB_PASSWORD=supersecret123
์์ 3: ๊ฐ๋ฐ ํ๊ฒฝ¶
# docker-compose.dev.yml
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- .:/app # ์์ค ์ฝ๋ ๋ง์ดํธ
- /app/node_modules # node_modules ๋ณดํธ
environment:
- NODE_ENV=development
command: npm run dev # ๊ฐ๋ฐ ์๋ฒ ์คํ
db:
image: postgres:15-alpine
environment:
- POSTGRES_PASSWORD=devpass
ports:
- "5432:5432" # ๋ก์ปฌ ์ ์ ํ์ฉ
์คํ:
# ๊ฐ๋ฐ ํ๊ฒฝ
docker compose -f docker-compose.dev.yml up
# ํ๋ก๋์
ํ๊ฒฝ
docker compose -f docker-compose.yml up -d
7. ์ ์ฉํ ํจํด¶
ํ๊ฒฝ๋ณ ์ค์ ๋ถ๋ฆฌ¶
# docker-compose.yml (๊ธฐ๋ณธ)
services:
app:
image: myapp
# docker-compose.override.yml (๊ฐ๋ฐ์ฉ, ์๋ ๋ณํฉ)
services:
app:
build: .
volumes:
- .:/app
# docker-compose.prod.yml (ํ๋ก๋์
์ฉ)
services:
app:
restart: always
# ๊ฐ๋ฐ: docker-compose.yml + docker-compose.override.yml ์๋ ๋ณํฉ
docker compose up
# ํ๋ก๋์
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
์๋น์ค ๋๊ธฐ (wait-for-it)¶
services:
app:
depends_on:
db:
condition: service_healthy
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
๋ช ๋ น์ด ์์ฝ¶
| ๋ช ๋ น์ด | ์ค๋ช |
|---|---|
docker compose up |
์๋น์ค ์์ |
docker compose up -d |
๋ฐฑ๊ทธ๋ผ์ด๋ ์์ |
docker compose up --build |
์ฌ๋น๋ ํ ์์ |
docker compose down |
์๋น์ค ์ค์ง ๋ฐ ์ญ์ |
docker compose down -v |
๋ณผ๋ฅจ๋ ์ญ์ |
docker compose ps |
์๋น์ค ์ํ |
docker compose logs |
๋ก๊ทธ ํ์ธ |
docker compose logs -f |
์ค์๊ฐ ๋ก๊ทธ |
docker compose exec ์๋น์ค ๋ช
๋ น |
๋ช ๋ น ์คํ |
docker compose restart |
์ฌ์์ |
๋ค์ ๋จ๊ณ¶
05_Practical_Examples.md์์ ์ค์ ํ๋ก์ ํธ์ Docker๋ฅผ ์ ์ฉํด๋ด ์๋ค!