Infra & Network

[Docker | Part 3] Docker Compose

hrbds 2026. 4. 30. 15:48

목차

  • WHY — 왜 Docker Compose가 필요한가
  • docker-compose.yml 구조
  • 서비스 간 DNS 통신
  • healthcheck + depends_on
  • .env 파일로 환경변수 분리
  • 핵심 명령어 정리
  • 환경별 Compose 파일 분리
  • 전체 요약

1. WHY — 왜 Docker Compose가 필요한가

로컬에서 띄운다고 하면

docker run -d --name mysql \
  -e MYSQL_ROOT_PASSWORD=ari1234 \
  -e MYSQL_DATABASE=aridb \
  -p 3306:3306 \
  mysql:8

docker run -d --name redis \
  -p 6379:6379 \
  redis:7.2

docker run -d --name ari-app \
  -p 8080:8080 \
  --link mysql --link redis \
  ari-app

 

서비스가 3개만 돼도 명령어가 이렇게 길어진다. 네트워크 연결, 환경변수, 실행 순서까지 고려하면 수동 관리가 불가능해진다.

Docker Compose는 이걸 하나의 파일로 해결한다.

docker compose up -d

 

한 줄로 전체 스택이 올라온다.


2. docker-compose.yml 구조

services:
  redis:
    image: redis:7.2
    container_name: ari-redis
    ports:
      - "6379:6379"
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 3

  mysql:
    image: mysql:8
    container_name: ari-mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-p${MYSQL_ROOT_PASSWORD}"]
      interval: 5s
      timeout: 3s
      retries: 10

 

주요 항목 설명
image 사용할 Docker 이미지
container_name 컨테이너 이름 지정
ports 호스트:컨테이너 포트 매핑
environment 환경변수 설정
healthcheck 컨테이너 상태 확인 설정

3. 서비스 간 DNS 통신

Compose는 서비스들을 같은 네트워크에 자동으로 연결한다. 같은 네트워크 안에서는 서비스 이름으로 DNS 통신이 가능하다.

docker exec -it ari-mysql sh -c "getent hosts redis"
# 172.19.0.3      redis

docker exec -it ari-mysql sh -c "getent hosts mysql"
# 172.19.0.2      mysql

 

서비스 이름이 자동으로 IP로 해석된다.

이 덕분에 Spring Boot 등에서 MySQL 접속 시 IP 대신 서비스 이름을 쓸 수 있다.

# application.yml
spring:
  datasource:
    url: jdbc:mysql://mysql:3306/aridb
  redis:
    host: redis
    port: 6379

 

IP가 바뀌어도 설정을 수정할 필요가 없다.


4. healthcheck + depends_on

단순히 depends_on: mysql만 쓰면 컨테이너가 시작됐다는 것만 보장한다.

MySQL이 실제로 요청을 받을 준비가 됐는지는 보장하지 못한다.

Spring Boot 앱이 MySQL보다 먼저 뜨면 DB 연결 실패가 발생한다.

healthcheck로 실제 준비 상태를 확인하고, depends_on으로 순서를 보장한다.

services:
  mysql:
    image: mysql:8
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 3s
      retries: 10

  app:
    image: ari-app
    depends_on:
      mysql:
        condition: service_healthy  ← mysql이 healthy 상태일 때만 앱 시작
      redis:
        condition: service_healthy

healthcheck 적용 후 docker compose ps 결과:

NAME        STATUS
ari-mysql   Up 5 seconds (healthy)   ← healthy 확인
ari-redis   Up 5 seconds (healthy)

5. .env 파일로 환경변수 분리

비밀번호, API 키 같은 민감한 정보를 docker-compose.yml에 직접 넣으면 git에 노출된다.

.env 파일로 분리하는 것이 실무 표준이다.

# .env
MYSQL_ROOT_PASSWORD=ari1234
MYSQL_DATABASE=aridb
# docker-compose.yml
environment:
  MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
  MYSQL_DATABASE: ${MYSQL_DATABASE}

 

.env는 반드시 .gitignore에 추가한다:

echo ".env" >> .gitignore
docker-compose.yml   → git에 올림 (공통 설정)
.env                 → git에 올리지 않음 (민감 정보)

 

.env 파일은 서버에서 직접 관리하고, docker-compose.yml은 git으로 공유하는 방식이다.


6. 핵심 명령어 정리

# 전체 서비스 시작 (백그라운드)
docker compose up -d

# 서비스 상태 확인
docker compose ps
docker compose ps -a  # 중지된 것 포함

# 로그 확인
docker compose logs           # 전체 서비스
docker compose logs mysql     # 특정 서비스
docker compose logs -f redis  # 실시간 로그

# 서비스 중지 / 시작
docker compose stop   # 컨테이너만 중지 (삭제 안 함)
docker compose start  # 중지된 컨테이너 재시작

# 정리
docker compose down            # 컨테이너 + 네트워크 삭제
docker compose down --volumes  # 볼륨(DB 데이터)까지 삭제

 

stop vs down 비교

명령어 컨테이너 네트워크 볼륨
stop 중지 유지 유지
down 삭제 삭제 유지
down --volumes 삭제 삭제 삭제

 

  • 잠깐 멈출 때 → stop
  • 완전히 정리할 때 → down
  • DB 초기화할 때 → down --volumes

7. 환경별 Compose 파일 분리

하나의 docker-compose.yml로 개발/운영 환경을 모두 관리하면 설정이 복잡해진다.

파일을 분리하고 -f 옵션으로 오버라이드하는 방식이 표준이다.

docker-compose.yml         ← 공통 설정 (git에 올림)
docker-compose.dev.yml     ← 개발 전용 오버라이드
docker-compose.prod.yml    ← 운영 전용 오버라이드
# 개발 환경
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# 운영 환경
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

 

두 번째 파일이 첫 번째 파일을 오버라이드(덮어쓰기) 한다.

공통 설정은 그대로 두고, 환경별로 다른 부분만 재정의하는 구조다.

# docker-compose.dev.yml
services:
  mysql:
    environment:
      MYSQL_ROOT_PASSWORD: dev1234
      MYSQL_DATABASE: aridb_dev

# docker-compose.prod.yml
services:
  mysql:
    environment:
      MYSQL_ROOT_PASSWORD: prod_super_secret
      MYSQL_DATABASE: aridb_prod

 

실제로 개발 환경(docker-compose.dev.yml)으로 띄운 후 확인한다.

docker exec -it ari-mysql mysql -uroot -pdev1234 -e "show databases;"

+--------------------+
| Database           |
+--------------------+
| aridb_dev          |   ← dev 설정이 적용됨
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

 


8. 전체 요약

Docker Compose 핵심 원칙
├── docker-compose.yml: 서비스 정의 (image / ports / environment / healthcheck)
├── 서비스 간 통신: 서비스 이름으로 DNS 자동 해석 (IP 불필요)
├── healthcheck + depends_on: 실제 준비 상태 확인 후 순서 보장
├── .env 파일: 민감 정보 분리 → .gitignore 추가 필수
└── 환경별 분리: -f 옵션으로 dev/prod 오버라이드