Docker Compose 2026: 멀티 컨테이너 애플리케이션, 네트워킹, DevOps 면접 질문

Docker Compose를 활용한 멀티 컨테이너 애플리케이션 구축 방법을 설명합니다. 네트워크 설정, 볼륨 관리, 프로덕션 배포 패턴과 DevOps 면접에서 자주 출제되는 질문과 답변을 다룹니다.

Docker Compose 2026: 멀티 컨테이너 애플리케이션, 네트워킹, DevOps 면접 질문

Docker Compose는 2026년 현재에도 멀티 컨테이너 Docker 애플리케이션을 정의하고 실행하는 표준 도구로 널리 사용되고 있습니다. 로컬 개발 환경 구축부터 DevOps 면접 준비까지, Compose의 네트워킹, 서비스 의존성, 프로덕션 패턴에 대한 이해는 주니어 엔지니어와 시니어 엔지니어를 구분하는 핵심 요소입니다.

핵심 포인트

Docker Compose는 선언적 YAML 형식을 사용하여 서비스, 네트워크, 볼륨을 단일 파일에 정의합니다. docker compose up 명령어 하나로 격리된 네트워크와 영구 스토리지를 갖춘 전체 애플리케이션 스택이 시작됩니다.

Docker Compose 아키텍처 이해하기

Docker Compose는 간단한 원칙으로 동작합니다. 애플리케이션의 서비스를 compose.yaml 파일(기존 docker-compose.yml을 대체하는 현대적 명명 규칙)에 정의하면, Compose가 컨테이너 생성, 네트워킹, 라이프사이클 관리를 처리합니다.

Docker Compose 명세는 세 가지 핵심 개념을 정의합니다:

  • 서비스: 이미지, 빌드 컨텍스트, 환경 변수, 리소스 제한을 포함하는 컨테이너 구성
  • 네트워크: 서비스 간 격리된 통신 채널
  • 볼륨: 컨테이너 재시작 후에도 유지되는 영구 데이터 저장소
yaml
# compose.yaml
services:
  api:
    build: ./api
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://db:5432/app
    depends_on:
      db:
        condition: service_healthy
    networks:
      - backend

  db:
    image: postgres:16
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=app
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - backend

networks:
  backend:
    driver: bridge

volumes:
  postgres_data:

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

이 구성은 의존성 순서 지정을 위한 헬스 체크, 민감한 데이터를 위한 Docker 시크릿, 영속성을 위한 명명된 볼륨, 명시적 네트워크 정의 등 프로덕션 준비 패턴을 보여줍니다.

Docker Compose 네트워킹 심층 분석

기본적으로 Compose는 애플리케이션을 위한 단일 네트워크를 생성합니다. 모든 서비스가 이 네트워크에 참여하고 서비스 이름을 호스트명으로 사용하여 서로 통신할 수 있습니다. 이 네트워킹 모델을 이해하는 것은 이후 Kubernetes 마이그레이션의 기초가 됩니다.

yaml
# compose.yaml
services:
  frontend:
    build: ./frontend
    ports:
      - "80:80"
    networks:
      - frontend-net
      - backend-net

  api:
    build: ./api
    networks:
      - backend-net

  cache:
    image: redis:7-alpine
    networks:
      - backend-net

  db:
    image: postgres:16
    networks:
      - backend-net

networks:
  frontend-net:
    driver: bridge
  backend-net:
    driver: bridge
    internal: true

internal: true 플래그는 백엔드 네트워크가 외부 인터넷에 접근하는 것을 방지합니다. 프론트엔드 서비스는 두 네트워크를 브릿지하여 유일한 진입점 역할을 합니다. 이러한 네트워크 세그멘테이션은 프로덕션 보안 관행을 반영합니다.

DNS 해석

Docker의 내장 DNS 서버는 서비스 이름을 자동으로 해석합니다. api 서비스는 수동 IP 구성 없이 db:5432로 데이터베이스에 연결할 수 있습니다.

Compose와 멀티스테이지 빌드

프로덕션 이미지는 최소화되어야 합니다. 멀티스테이지 빌드와 Compose 프로필을 결합하면 개발과 프로덕션에서 서로 다른 구성이 가능합니다.

dockerfile
# api/Dockerfile
# Stage 1: Build
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:22-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]

# Stage 3: Development
FROM node:22-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
USER node
CMD ["npm", "run", "dev"]
yaml
# compose.yaml
services:
  api:
    build:
      context: ./api
      target: ${BUILD_TARGET:-production}
    volumes:
      - ${API_VOLUMES:-./api/dist:/app/dist:ro}
    profiles:
      - ${COMPOSE_PROFILES:-prod}

BUILD_TARGET=development COMPOSE_PROFILES=dev docker compose up을 실행하면 핫 리로드가 적용된 개발 구성이 시작됩니다.

서비스 의존성과 헬스 체크

depends_on 지시어는 시작 순서를 제어하지만, 컨테이너가 시작되었다고 해서 서비스가 준비된 것은 아닙니다. 헬스 체크가 이 타이밍 문제를 해결합니다. 이 패턴은 DevOps 면접에서 자주 질문됩니다.

yaml
# compose.yaml
services:
  api:
    build: ./api
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
      migrations:
        condition: service_completed_successfully

  migrations:
    build: ./api
    command: npm run migrate
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

  cache:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3

세 가지 의존성 조건이 존재합니다:

  • service_started: 기본값, 컨테이너가 시작된 상태
  • service_healthy: 헬스 체크를 통과한 상태
  • service_completed_successfully: 컨테이너가 종료 코드 0으로 종료된 상태(초기화 컨테이너용)

DevOps 면접 준비가 되셨나요?

인터랙티브 시뮬레이터, flashcards, 기술 테스트로 연습하세요.

로컬 개발을 위한 Docker Compose

개발 환경은 바인드 마운트, 환경 변수 오버라이드, 디버깅 도구의 이점을 누립니다. compose.override.yaml 파일은 compose.yaml과 자동으로 병합됩니다.

yaml
# compose.yaml (기본 구성)
services:
  api:
    build: ./api
    environment:
      - NODE_ENV=production

  db:
    image: postgres:16
yaml
# compose.override.yaml (개발 오버라이드)
services:
  api:
    build:
      target: development
    volumes:
      - ./api:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DEBUG=app:*
    ports:
      - "9229:9229"

  db:
    ports:
      - "5432:5432"

익명 볼륨 /app/node_modules는 호스트의 node_modules가 컨테이너에 설치된 의존성을 덮어쓰는 것을 방지합니다.

프로덕션 배포 패턴

Docker Compose는 단일 호스트 프로덕션 배포에 적합합니다. 멀티 호스트 오케스트레이션에는 Kubernetes와 Helm이 더 나은 확장성을 제공하지만, Compose는 소규모 애플리케이션에 여전히 유효합니다.

yaml
# compose.prod.yaml
services:
  api:
    image: registry.example.com/api:${VERSION:-latest}
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
        reservations:
          cpus: "0.25"
          memory: 256M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/nginx/certs:ro
    depends_on:
      - api

deploy 키는 리소스 제한, 레플리카 수, 재시작 정책을 구성합니다. docker compose -f compose.prod.yaml up -d를 실행하면 프로덕션 스택이 분리 모드로 시작됩니다.

환경 변수와 시크릿 관리

민감한 구성에는 적절한 처리가 필요합니다. Docker Compose는 .env 파일부터 Docker 시크릿까지 여러 접근 방식을 지원합니다.

bash
# .env
POSTGRES_PASSWORD=dev_password_only
API_SECRET_KEY=local_dev_key
yaml
# compose.yaml
services:
  api:
    environment:
      - API_SECRET_KEY  # 셸 또는 .env에서 상속
      - DATABASE_URL=postgres://user:${POSTGRES_PASSWORD}@db:5432/app
    env_file:
      - ./config/api.env

프로덕션에서는 Docker 시크릿이 환경 변수 대신 파일로 민감한 데이터를 마운트하여 더 나은 보안을 제공합니다:

yaml
# compose.prod.yaml
services:
  api:
    secrets:
      - api_key
      - db_password
    environment:
      - API_KEY_FILE=/run/secrets/api_key

secrets:
  api_key:
    external: true
  db_password:
    file: ./secrets/db_password.txt
보안 참고사항

프로덕션 시크릿이 포함된 .env 파일을 버전 관리에 커밋하면 안 됩니다. 프로덕션 배포에는 HashiCorp Vault나 클라우드 제공업체 솔루션과 같은 외부 시크릿 관리를 사용해야 합니다.

Docker Compose 관련 DevOps 면접 질문

면접관은 실용적인 시나리오를 통해 Compose 개념에 대한 이해도를 테스트합니다. 다음 질문들은 DevOps와 플랫폼 엔지니어링 면접에서 자주 출제됩니다.

Q: Compose 네트워크 내에서 컨테이너들은 어떻게 통신하나요?

Docker는 각 Compose 프로젝트에 전용 브릿지 네트워크를 생성합니다. 서비스는 서비스 이름을 호스트명으로 사용하여 통신합니다. 내장 DNS 서버가 이러한 이름을 컨테이너 IP 주소로 해석합니다. 외부 트래픽은 명시적으로 게시된 포트를 통해서만 서비스에 도달합니다.

Q: 기존 컨테이너가 있는 상태에서 docker compose up을 실행하면 어떻게 되나요?

Compose는 현재 구성을 실행 중인 컨테이너와 비교합니다. 변경되지 않은 서비스는 계속 실행됩니다. 수정된 서비스는 새 설정으로 재생성됩니다. 새 서비스는 새로 시작됩니다. 제거된 서비스는 중지 후 삭제됩니다.

Q: Compose에서 데이터베이스 마이그레이션을 어떻게 처리하나요?

두 가지 패턴이 있습니다. 첫째, service_completed_successfully 의존성을 가진 초기화 컨테이너를 사용하는 방법:

yaml
services:
  migrate:
    image: api:latest
    command: npm run migrate
    depends_on:
      db:
        condition: service_healthy

  api:
    depends_on:
      migrate:
        condition: service_completed_successfully

둘째, 애플리케이션 시작 스크립트에 마이그레이션 로직을 포함하여 트래픽을 수락하기 전에 보류 중인 마이그레이션을 확인하고 적용하는 방법이 있습니다.

Q: 볼륨과 바인드 마운트의 차이점은 무엇인가요?

명명된 볼륨은 Docker가 관리하고 /var/lib/docker/volumes에 저장되며 호스트 간에 이식 가능합니다. 바인드 마운트는 호스트 디렉토리를 컨테이너에 직접 매핑하여 개발에는 유용하지만 환경에 의존적입니다. 볼륨은 NFS나 클라우드 블록 스토리지와 같은 원격 스토리지용 드라이버를 지원합니다.

Q: docker-composedocker compose의 차이점은 무엇인가요?

하이픈이 있는 docker-compose는 현재 사용 중단된 Python 기반 V1 독립 실행 도구입니다. 공백으로 구분된 docker compose는 Docker CLI에 통합된 Go 기반 V2 구현입니다. V2는 더 빠르고 Compose 명세를 완전히 지원하며 활발하게 개발되고 있습니다.

Compose 애플리케이션 디버깅

컨테이너화된 애플리케이션의 문제 해결에는 특정 기법이 필요합니다. 다음 명령어들은 Compose 스택 내부에서 무슨 일이 일어나고 있는지 보여줍니다:

bash
# 모든 서비스의 로그 보기
docker compose logs -f

# 타임스탬프와 함께 특정 서비스의 로그 보기
docker compose logs -f --timestamps api

# 실행 중인 컨테이너에서 명령 실행
docker compose exec api sh

# 일회성 명령 실행(새 컨테이너 시작)
docker compose run --rm api npm test

# 리소스 사용량 보기
docker compose top
docker stats

# 네트워크 구성 검사
docker network inspect project_backend

# compose 파일 검증
docker compose config

docker compose config 명령어는 모든 compose 파일을 병합하고 최종 구성을 표시합니다. 변수 보간 문제를 디버깅할 때 매우 유용합니다.

결론

  • Docker Compose는 서비스, 네트워크, 볼륨을 단일 YAML 파일에서 멀티 컨테이너 애플리케이션으로 정의합니다
  • 서비스는 기본 브릿지 네트워크 내에서 서비스 이름을 호스트명으로 사용하여 DNS를 통해 통신합니다
  • service_healthy 조건이 있는 헬스 체크는 적절한 시작 순서를 보장합니다
  • 바인드 마운트와 디버그 포트 같은 개발 전용 설정에는 compose.override.yaml을 사용합니다
  • 프로덕션 배포에서는 리소스 제한, 재시작 정책, 민감한 데이터를 위한 Docker 시크릿이 유용합니다
  • docker compose CLI(V2)는 더 나은 성능과 기능으로 사용 중단된 docker-compose(V1)를 대체합니다

연습을 시작하세요!

면접 시뮬레이터와 기술 테스트로 지식을 테스트하세요.

공유

관련 기사