codingstairs
노트에듀라이프연락
⌕검색⌘K
koen

Navigation

  • Intro
  • Blog
  • Life

연락하기

로그인 없이도 보낼 수 있어요. 답변이 필요하면 이메일을 함께 적어 주세요.

  • 익명 폼으로 의견 남기기 →
  • ✉ warragon112@gmail.com
  • 카카오톡 오픈채팅 ↗

© 2026 codingstairs

  • 노트
  • 에듀
  • 검색
  • 라이프
  • 연락
  • 약관
  • RSS
  • GitHub
노트›infra

Docker Compose 패턴

2026-04-28 게시· 2026-05-18 갱신·0회 조회

Docker Compose 패턴

단일 호스트에서 여러 컨테이너 (웹 · DB · 캐시 · 큐) 를 함께 띄울 때 가장 가벼운 길이 Compose. YAML 한 파일로 의존 · 네트워크 · 볼륨 · 헬스체크를 묶음. 본격 오케스트레이터가 아니라는 점이 강점이자 한계. 이 글은 Compose 의 v1 vs v2 차이 · compose.yaml 핵심 키 · healthcheck · env_file · profiles · override 패턴.

1. Compose 에 대한 이야기

Compose 는 원래 Fig 라는 외부 도구 (2014) 였다가 Docker 가 인수해 흡수. v1 은 Python 으로 작성된 별도 CLI (docker-compose), v2 (2021) 부터 Go 로 재작성되어 docker compose 서브커맨드로 통합. v2 는 BuildKit · 프로필 · 더 빠른 실행이 차이.

권장 파일명은 compose.yaml 또는 compose.yml. 이전 관례인 docker-compose.yml 도 인식.

2. 기본 구조

services:
  web:
    build: ./web
    ports:
      - "127.0.0.1:8080:8080"
    environment:
      DATABASE_URL: postgres://app:${DB_PASS}@db:5432/app
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${DB_PASS}
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5

volumes:
  db-data:

3. 핵심 키

키 역할
services 컨테이너 단위 정의.
volumes 명명된 볼륨.
networks 사용자 정의 네트워크 (미정의 시 default 자동 생성).
secrets 비밀값 마운트 (파일 또는 외부 secret).
configs 설정 파일 마운트.
profiles 선택적 서비스 묶음.

4. 의존과 헬스체크

depends_on 만으로는 "다른 서비스가 살아 있다" 보장이 약함. 네트워크가 떴다 해도 DB 가 실제 쿼리 받을 준비 안 됐을 수 있음. v2 에서는 condition: service_healthy 와 healthcheck 결합으로 진짜 준비 상태 확인.

5. env_file 과 ${VAR} 치환

services:
  web:
    env_file: .env
    environment:
      LOG_LEVEL: ${LOG_LEVEL:-info}

env_file 은 컨테이너 안의 환경변수로 주입. ${VAR} 치환은 Compose 가 .env 파일과 셸 환경에서 읽어 YAML 자체를 채움. 두 자리는 의미가 다름 — 하나는 컨테이너 환경, 하나는 Compose 파일의 텍스트 치환.

6. profiles

특정 환경에서만 띄우고 싶은 서비스에 프로필을 붙임:

services:
  app: { ... }
  pgadmin:
    image: dpage/pgadmin4
    profiles: ["dev"]

docker compose --profile dev up 으로 dev 프로필 서비스까지 함께. 운영에서 불필요한 도구를 자연스럽게 빼는 데 유용.

7. override 파일

compose.yaml 옆의 compose.override.yaml 은 자동 병합. 환경별 분기에는 명시적 파일을 쓰는 편이 명확:

docker compose -f compose.yaml -f compose.prod.yaml up -d

뒤에 오는 파일이 앞을 덮어씀. 개발 / 스테이징 / 운영 차이를 작은 패치 파일로 분리하는 패턴이 흔합니다.

8. extends

다른 파일의 서비스 정의를 상속 · 합성. 큰 모노레포에서 공통 베이스를 정의하는 자리:

services:
  app:
    extends:
      file: common.yaml
      service: app-base

9. 다른 길

Compose 와 비교 대상은 단일 호스트 한정.

  • systemd unit + Docker — 서비스 정의를 systemd 가 관리. 의존 그래프는 systemd 의 After= · Requires=.
  • Podman + quadlet — Podman 의 systemd 통합. *.container 파일에서 컨테이너 정의.
  • Nomad (HashiCorp) — 단일 바이너리의 가벼운 오케스트레이터. 단일 호스트 ~ 수백 노드.
  • Kubernetes — 다른 무게 클래스. 단일 호스트에 쓰면 운영 비용이 과하다는 평.

여러 호스트로 나가는 순간 Compose 는 부족. Swarm · Nomad · k8s 로 옮김.

10. 단일 호스트 적합성

장점 — 학습 비용 작음, 단일 파일에 모든 정의, 빠른 시작 / 종료.

한계 — 단일 호스트 (수평 확장 없음). 무중단 배포는 외부 도구나 수동 절차 필요. 시크릿 관리 · 롤링 업그레이드 약함.

대다수 사이드 프로젝트 · 중소 서비스는 단일 호스트 + Compose 로 충분.

11. 자주 쓰는 모양

빌드와 이미지 분리:

services:
  app:
    image: ghcr.io/my/app:1.4.2
    build: ./app

CI 에서 docker compose build 후 push. 운영 호스트에서는 pull. image 와 build 를 함께 두면 두 흐름이 자연스럽게 합쳐짐.

로깅 · 재시작 — 기본 로그 드라이버의 디스크 무한 증가 방지:

services:
  app:
    restart: unless-stopped
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "5"

YAML anchor 로 일괄 적용 — 같은 logging 블록을 모든 service 에 매번 적기 보다 anchor 한 곳에서 정의하고 참조:

x-logging: &default-logging
  driver: json-file
  options:
    max-size: "10m"
    max-file: "3"

services:
  web:
    logging: *default-logging
  db:
    logging: *default-logging

x- 접두사는 Compose 의 "확장 필드" — Compose 가 무시하지만 YAML 파서는 anchor 로 인식. 정책 변경의 단일 지점. 무설정 시 json-file 기본이 무제한 누적되므로, anchor 없이 시작해도 결국 모든 service 에 동일 블록을 붙이게 됨. 처음부터 anchor 가 깔끔.

12. 자주 걸리는 자리

포트 바인딩 주소 누락 — "8080:8080" 은 0.0.0.0 에 바인딩되어 외부 접근 가능. 운영 보안 모델에서는 "127.0.0.1:8080:8080" 이 적절할 때가 많음.

depends_on 만으로 충분하다는 오해 — condition 없이는 단순 시작 순서만 보장.

볼륨 vs 바인드 마운트의 권한 — 호스트 사용자 (uid) 와 컨테이너 사용자가 다르면 쓰기 실패가 자주.

.env 파일의 보안 — Compose 의 ${VAR} 치환을 위해 평문으로 저장. 시크릿은 별도 도구 (Docker secret · age · sops) 로 분리.

이름 충돌 — 같은 호스트에서 여러 Compose 프로젝트를 돌릴 때 프로젝트 이름이 같으면 컨테이너 · 네트워크가 섞임. --project-name 또는 디렉터리 분리.

하고픈 말

Compose 는 단일 호스트의 모든 자리를 단일 YAML 로 묶는 가장 직관적인 도구. healthcheck + condition: service_healthy + 127.0.0.1 바인딩 + override 파일 분기 네 자리가 함께 있을 때 운영의 안정성이 크게 좋아집니다.

Next

  • caddy-not-nginx
  • loopback-ssh-tunnel

Compose 공식 문서 · Compose Specification · Compose 파일 레퍼런스 · Healthcheck 문서 · Profiles 문서 · Podman + quadlet 을 참고합니다.

infra 카테고리의 다른 글

카테고리 전체 보기 →
  • 클라우드 에뮬레이터 스택 — 4번째 환경의 설계
  • 로컬 HTTPS — mkcert 와 자체 CA
  • 단일 서버 운영의 자리
  • 루프백 바인딩과 SSH 터널
  • Caddy 와 nginx — 비교의 자리
  • Docker 기초