개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Docker Compose 프로덕션 환경 구성 — 실무 배포를 위한 설정

2025년 10월 30일
Docker프로덕션Restart PolicyResource Limits로그

개발 환경의 docker-compose.yml을 그대로 프로덕션에 올리면 장애 시 컨테이너가 재시작되지 않고, 메모리를 무제한으로 소비하며, 로그가 디스크를 가득 채운다. 실무에서는 개발용과 프로덕션용 Compose 파일을 분리하고, 재시작 정책·리소스 제한·로그 드라이버를 명시적으로 선언해야 한다. 이 글은 그 핵심 설정을 하나씩 짚는다.

프로덕션 Dockerfile 분리

개발용 이미지에는 devDependency, hot-reload 도구, 소스 마운트가 포함된다. 프로덕션 이미지는 멀티 스테이지 빌드로 최소화한다.

# Dockerfile.prod
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/main.js"]

Compose에서는 build.dockerfile로 지정한다.

services:
  api:
    build:
      context: .
      dockerfile: Dockerfile.prod

Restart Policy

컨테이너가 비정상 종료되면 자동 재시작이 필요하다. restart: always 는 Docker 데몬 재시작 후에도 컨테이너를 복구한다.

services:
  api:
    restart: always
  worker:
    restart: on-failure   # 비정상 종료 시에만 재시작

on-failure — exit code가 0이 아닐 때만 재시작. 의도적 종료(exit 0)는 재시작하지 않는다.

Resource Limits

리소스 제한 없이 배포하면 단일 컨테이너가 호스트 전체 메모리를 점유할 수 있다. deploy.resources로 상한을 설정한다.

services:
  api:
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512m
        reservations:
          memory: 256m

reservations — 컨테이너 시작 시 호스트에서 보장받는 최소 자원. 스케줄러가 배치 결정에 활용한다.

로그 드라이버 설정

기본 로그 드라이버(json-file)는 로테이션 없이 디스크를 무한 증가시킨다. max-size와 max-file을 반드시 지정한다.

services:
  api:
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

중앙 집중 로깅이 필요하면 driver: fluentd 또는 driver: awslogs로 교체한다.

시크릿 관리

환경 변수로 DB 패스워드를 넘기면 docker inspect로 노출된다. Docker Secrets 또는 외부 시크릿 매니저를 사용한다.

secrets:
  db_password:
    file: ./secrets/db_password.txt

services:
  db:
    image: postgres:16
    secrets:
      - db_password
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password

시크릿 파일은 컨테이너 내부 /run/secrets/<name> 경로에 마운트된다. 환경 변수가 아니라 파일로 읽는다.

CI/CD 연동 흐름

push to main
     │
     ▼
[CI] docker build -f Dockerfile.prod -t app:$SHA .
     │
     ▼
[CI] docker push registry/app:$SHA
     │
     ▼
[CD] ssh prod-server
     "IMAGE_TAG=$SHA docker compose -f compose.prod.yml up -d"

compose.prod.yml에서 이미지 태그를 환경 변수로 받으면 CI/CD 파이프라인에서 롤백이 쉬워진다.

services:
  api:
    image: registry/app:${IMAGE_TAG}

개발·프로덕션 파일 분리 전략

파일용도
compose.yml공통 서비스 정의
compose.override.yml개발 전용 볼륨·포트
compose.prod.yml프로덕션 전용 리소스·로그·시크릿

docker compose -f compose.yml -f compose.prod.yml up -d 처럼 파일을 명시적으로 병합해 실행한다. compose.override.yml은 docker compose up 시 자동 적용되므로 프로덕션에서는 반드시 파일을 명시해야 한다.

← 이전 글Docker Compose 개발 환경 구성 — 로컬 개발을 위한 실무 설정
다음 글 →Docker Compose 모니터링 — Prometheus와 Grafana를 Compose로 구성