[도커 #8] 컴포즈

도커 컴포즈 개념부터 도커의 DNS와 디스커버리 공부 Docker Compose 기반 멀티 컨테이너 구성 실습까지 진행하였습니다.
도경원's avatar
Aug 01, 2025
[도커 #8] 컴포즈

1. 도커 컴포즈(Docker Compose)란 ?

여러 개의 Docker 컨테이너를 하나의 docker-compose.yml 파일로 정의하고 실행 할 수 있게 도와주는 도구이다. 마치 지휘자처럼 여러 서비스를 한 번에 관리한다.
💬
예시) Spring 서버, MySQL, Redis, Nginx 등을 하나의 명령으로 up , down
로컬 개발 환경에서 멀티 컨테이너 구성을 빠르게 테스트할 때 사용하고, 배포용으로는 적합하지 않다.
배포는 더 강력한 오케스트레이터(Kubernetes, AWS ECS 등)을 사용

2. Compose 실행 구조

docker-compose up 명령어는 내부적으로 다음 두 단계를 자동 실행한다.
  • docker build (→ Dockerfile 기반으로 이미지 빌드)
  • docker run (→ 실제 컨테이너 실행)
이미지 빌드시, 내부적으로 빌드 전용 임시 컨테이너가 만들어져서 이미지 생성 후 삭제된다. 그 후 실제 서비스용 컨테이너가 뜨는 것이다. 그래서 "하나 실행되고, 리얼 컨테이너가 실행된다"는 표현이 나온 것이다.
docker-compose는 컨테이너를 실행할 때 환경변수 주입한다. 따라서 .env 파일 또는 environment: 키워드를 활용해야 확실하다.
이 시점에서 환경변수는 OS 레벨이 아니라, 컨테이너 내부 프로세스에 전달된다. 즉, 환경변수 설정 이후에 실행되는 명령어만 영향을 받는다.
notion image
Dockerfile에 서비스명을 ENV RDS_HOSTNAME=my_db 처럼 하면 이미지를 빌드하는 시점에는 my_db 컨테이너가 아직 존재하지 않는다. 따라서 DNS에 등록도 안되어 있음 무효한 설정이 들어가게 됨 즉 시점 차이를 잘 이해해야한다. 따라서 명심하자 환경변수는 docker-compose.yml에서 설정해야한다.

3. Dockerfile 중심의 구성

docker-compose.ymlimage: ~ 쓰지말고, 대신 build: 속성으로 Dockerfile 기반 빌드를 유도하면 이미지 관리가 깔끔해지고, 버전 충돌 방지에 유리하다.
notion image

4. Docker의 DNS와 서비스 디스커버리

DNS (Domain Name System)

: 사람이 읽을 수 있는 도메인 이름(예: google.com)을 컴퓨터가 이해할 수 있는 IP 주소(예: 142.250.72.206)로 변환해주는 시스템이다. 즉, “이름 → IP 주소” 매핑을 자동으로 해준다.

Docker에서의 DNS는 ?

: 도커는 자체 DNS 서버를 가지고 있다. 같은 네트워크 안에 있는 컨테이너들끼리 이름으로 통신 할 수 있게 도와준다.
  • 두 컨테이너는 같은 커스텀 네트워크에 속해야 한다.
  • 각 컨테이너의 이름이 자동으로 도커 DNS에 등록됨
  • IP 주소를 직접 몰라도 됨 (동적 IP 문제 해결)

서비스 디스커버리는 ?

: 서비스 이름만으로 다른 서비스(컨테이너)에 접근할 수 있도록 하는 기능이다. 도커의 DNS가 제공하는 핵심 기능 중 하나이고, 컨테이너 간 통신을 자동화하고 IP 관리를 없애주는 메커니즘이다.

5. 명령어 정리

명령어
설명
docker-compose up -d
빌드 + 런까지 자동, 백그라운드 실행
docker-compose down
전체 종료 및 네트워크 정리
docker-compose build
Dockerfile 기반 이미지 빌드만
docker-compose logs
로그 확인
docker-compose exec <서비스명> bash
실행 중인 컨테이너에 터미널 접속

6. [실습] Docker Compose 기반 멀티 컨테이너 구성 실습 - Spring 서버 + MySQL 연동

이 실습을 통하여 서비스 디스커버리, 환경변수 관리, 네트워크 구성까지 한번 잡아보았다.

디렉토리 구조

notion image
ex07/ ├── db/ │ ├── Dockerfile # DB(MySQL) 이미지를 커스터마이징하기 위한 설정 │ └── init.sql # DB 초기화용 SQL 스크립트 (예: 테이블 생성, 데이터 삽입 등) ├── server/ │ ├── Dockerfile # 서버(Spring, Node 등) 이미지를 커스터마이징하는 설정 │ └── entrypoint.sh # 컨테이너 시작 시 실행되는 스크립트 (ex. 마이그레이션, 실행) ├── docker-compose.yml # 전체 컨테이너 조합을 정의한 구성 파일
💡
정석적인 도커 멀티 컨테이너 프로젝트 구조다.

docker-compose.yml 코드 분석

notion image
  • ./server/Dockerfile을 기반으로 서버 애플리케이션 컨테이너 생성
notion image
  • 외부에서 localhost:8080으로 접근하면 컨테이너 내부의 80 포트와 연결됨 (예: Spring 웹 서버)
  • 서버가 죽어도 재시작됨
  • my_db가 먼저 실행된 후, my_server가 실행됨, 데이터베이스가 준비되기 전에 서버가 먼저 실행되는 것을 방지
notion image
  • my_server에 환경변수 전달
  • 코드 내부에서 DB 접속할 때 사용됨
String url = "jdbc:mysql://" + RDS_HOSTNAME + ":" + RDS_PORT + "/" + RDS_DB_NAME;
notion image
  • backend_network 라는 네트워크에 속해 있음
  • 같은 네트워크에 속해있는 서비스와 통신 가능
notion image
  • backend_networkmy_db, my_server내부 통신을 위해 사용하는 네트워크
  • frontend_network → 현재는 아무 서비스에도 안 붙어있음. 추후 프론트엔드 서비스 붙일 때 사용할 수 있음.

전체 실습 코드

version: '3.8' services: my_db: build: context: ./db ports: - "3306:3306" restart: always networks: - backend_network my_server: build: context: ./server ports: - "8080:80" restart: always depends_on: - my_db environment: - RDS_HOSTNAME=my_db - RDS_PORT=3306 - RDS_USERNAME=ssar - RDS_PASSWORD=ssar1234 - RDS_DB_NAME=blogdb networks: - backend_network networks: backend_network: driver: bridge frontend_network: driver: bridge
💬
항목
설명
my_db
커스텀 MySQL 컨테이너 (3306 노출)
my_server
Spring 또는 웹 서버 컨테이너 (8080 노출)
depends_on
DB가 먼저 실행되어야 서버가 실행됨
RDS_HOSTNAME=my_db
도커 DNS를 통해 이름 기반 DB 접속 가능
networks
같은 네트워크 안에 있어야 이름 기반 통신(DNS) 가능
entrypoint.sh
서버 시작 전에 초기 실행할 작업들을 정의 (예: 마이그레이션)
init.sql
DB 최초 실행 시 초기 데이터 삽입 또는 스키마 구성
notion image
 
Share article

Gyeongwon's blog