Docker

Docker compose란?

yj992233 2026. 5. 14. 13:28

⭐ Docker Compose란?

Docker Compose는 여러 개의 Docker 컨테이너를 하나의 설정 파일로 정의하고 실행할 수 있게 해주는 도구다.

쉽게 말하면, 여러 컨테이너를 한 번에 관리하기 위한 도구다.

 

Docker만 사용할 때는 컨테이너를 하나씩 실행해야 한다.

docker run ...
docker run ...
docker run ...
 

하지만 Docker Compose를 사용하면 compose.yml 파일에 필요한 서비스들을 미리 정의해두고, 명령어 하나로 전체 컨테이너를 실행할 수 있다.

docker compose up
 

즉, Docker Compose는 다음과 같은 역할을 한다.

여러 컨테이너 실행
컨테이너 간 네트워크 연결
환경 변수 설정
포트 연결
볼륨 설정
실행 순서 관리
 

한 문장으로 정리하면 다음과 같다.

Docker Compose는 여러 컨테이너로 구성된 애플리케이션을 하나의 설정 파일로 관리하고 실행하는 도구다.
 

Docker Compose가 필요한 이유?

Docker Compose가 필요한 이유는 실제 서비스가 보통 하나의 컨테이너로만 구성되지 않기 때문이다.

 

Spring Boot 애플리케이션을 예로 들어보자.

Spring Boot 서버는 혼자 실행될 수는 있지만, 실제 기능을 수행하려면 데이터베이스가 필요할 수 있다.

Spring Boot 서버 → MySQL 데이터베이스 연결
 

또 로그인 세션이나 캐시를 위해 Redis가 필요할 수도 있다.

Spring Boot 서버 → Redis 연결
 

이때 Docker 명령어만으로 실행하면 다음처럼 복잡해진다.

docker network create app-network
docker run --name mysql --network app-network -e MYSQL_ROOT_PASSWORD=1234 ...
docker run --name redis --network app-network ...
docker run --name spring-app --network app-network -p 8080:8080 ...
 

명령어가 길고, 실수하기도 쉽다. 다른 개발자에게 같은 환경을 공유하기도 불편하다.

 

Docker Compose를 사용하면 이 모든 설정을 파일 하나에 정리할 수 있다.

compose.yml
 

그리고 명령어 하나로 실행한다.

docker compose up
 

이렇게 하면 새로 합류한 개발자도 복잡한 설치 과정을 거치지 않고 같은 개발 환경을 실행할 수 있다.


⭐Dockerfile과 Docker Compose의 차이

Docker Compose를 이해할 때 Dockerfile과 헷갈릴 수 있다.

둘은 역할이 다르다.

구분 Dockerfile Docker Compose
목적 Docker 이미지를 만드는 방법 정의 여러 컨테이너 실행 방법 정의
대상 하나의 애플리케이션 이미지 여러 서비스와 컨테이너
예시 Spring Boot 이미지를 어떻게 만들지 작성 Spring Boot, MySQL, Redis를 어떻게 함께 실행할지 작성
파일 Dockerfile compose.yml 또는 docker-compose.yml

쉽게 말하면 다음과 같다.

Dockerfile은 컨테이너 하나의 이미지를 만드는 레시피다.
Docker Compose는 여러 컨테이너를 함께 실행하는 실행 계획서다.
 

예를 들어 Spring Boot 애플리케이션을 Docker로 실행한다고 해보자.

 

Dockerfile은 Spring Boot 애플리케이션 이미지를 만드는 방법을 정의한다.

FROM eclipse-temurin:17-jre
WORKDIR /app
COPY build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
 

반면 compose.yml은 Spring Boot 컨테이너와 MySQL 컨테이너를 어떻게 함께 실행할지 정의한다.

services:
  app:
    build: .
    ports:
      - "8080:8080"

  mysql:
    image: mysql:8.0
 

즉, Dockerfile과 Docker Compose는 경쟁 관계가 아니라 함께 사용하는 관계다.


⭐ compose.yml 기본 구조

Docker Compose 설정 파일은 보통 compose.yml 또는 docker-compose.yml이라는 이름을 사용한다.

기본 구조는 다음과 같다.

services:
  app:
    image: spring-app:1.0
    ports:
      - "8080:8080"
 

여기서 가장 중요한 키워드는 services다.

services 아래에는 실행할 컨테이너들을 정의한다.

 

예를 들어 Spring Boot 애플리케이션과 MySQL을 함께 실행한다면 다음처럼 작성할 수 있다.

services:
  app:
    build: .
    ports:
      - "8080:8080"

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: 1234
      MYSQL_DATABASE: app_db
 

여기서 app과 mysql은 각각 하나의 서비스 이름이다. Docker Compose는 이 서비스들을 각각 컨테이너로 실행한다.


 

이제 실제 예시를 보자.

 

Spring Boot 애플리케이션과 MySQL을 Docker Compose로 함께 실행한다고 해보자.

프로젝트 구조는 다음과 같다.

spring-compose-demo/
--- Dockerfile
--- compose.yml
--- build.gradle
--- settings.gradle
--- src/
 

먼저 Spring Boot 애플리케이션을 위한 Dockerfile을 작성한다.

FROM eclipse-temurin:17-jre

WORKDIR /app

COPY build/libs/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]
 

이 Dockerfile은 빌드된 jar 파일을 컨테이너 안에 복사하고, java -jar app.jar로 실행한다.

 

그다음 compose.yml을 작성한다.

services:
  app:
    build: .
    container_name: spring-app
    ports:
      - "8080:8080"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/app_db
      SPRING_DATASOURCE_USERNAME: app_user
      SPRING_DATASOURCE_PASSWORD: app_password
    depends_on:
      - mysql

  mysql:
    image: mysql:8.0
    container_name: mysql-db
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: app_password
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:
 

이 파일 하나에 Spring Boot와 MySQL 실행 정보가 모두 들어 있다.


1️⃣ services

services:
 

services는 Docker Compose에서 실행할 컨테이너 목록을 정의하는 영역이다.

 

여기서는 두 개의 서비스를 정의했다.

app
mysql
 

app은 Spring Boot 애플리케이션이고, mysql은 MySQL 데이터베이스다.

2️⃣ app 서비스

app:
  build: .
 

build: .은 현재 디렉터리의 Dockerfile을 사용해서 이미지를 빌드하겠다는 의미다.

 

즉, Compose가 직접 Spring Boot 애플리케이션 이미지를 만든다.

현재 디렉터리 Dockerfile
→ Docker 이미지 빌드
→ app 컨테이너 실행

 

3️⃣ ports

ports:
  - "8080:8080"
 

이 설정은 포트 연결을 의미한다.

내 컴퓨터의 8080번 포트
→ 컨테이너 내부의 8080번 포트
 

그래서 브라우저에서 다음 주소로 접근할 수 있다.

http://localhost:8080
 

MySQL도 마찬가지다.

ports:
  - "3306:3306"
 

이 설정은 내 컴퓨터에서 MySQL 컨테이너의 3306번 포트로 접근할 수 있게 한다.

4️⃣ environment

environment:
  SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/app_db
  SPRING_DATASOURCE_USERNAME: app_user
  SPRING_DATASOURCE_PASSWORD: app_password
 

environment는 컨테이너 안에서 사용할 환경 변수를 지정한다.

Spring Boot에서는 환경 변수를 통해 DB 접속 정보를 주입할 수 있다.

 

여기서 중요한 부분은 이 주소다.

jdbc:mysql://mysql:3306/app_db
 

보통 로컬에서 MySQL에 접속할 때는 localhost를 사용한다.

 

하지만 Docker Compose 내부에서는 localhost를 사용하면 안 되는 경우가 많다.

왜냐하면 Spring Boot 컨테이너 안에서 localhost는 MySQL 컨테이너가 아니라 자기 자신을 의미하기 때문이다.

 

Docker Compose에서는 같은 네트워크 안에 있는 서비스끼리 서비스 이름으로 접근할 수 있다.

mysql 서비스 이름 → mysql 컨테이너 주소로 동작
 

그래서 Spring Boot 컨테이너는 MySQL에 접속할 때 다음 주소를 사용한다.

mysql:3306
 

이 부분이 Docker Compose에서 매우 중요하다.

5️⃣ depends_on

depends_on:
  - mysql
 

depends_on은 컨테이너 실행 순서를 지정한다.

위 설정은 app 서비스를 실행하기 전에 mysql 서비스를 먼저 시작하라는 의미다.

 

다만 주의할 점이 있다.

 

depends_on은 MySQL 컨테이너를 먼저 시작해주지만, MySQL이 완전히 준비될 때까지 기다려준다는 뜻은 아니다.

 

즉, MySQL 컨테이너가 실행은 되었지만 아직 DB 연결을 받을 준비가 안 되었을 수 있다.

 

이 경우 Spring Boot 애플리케이션이 처음에 DB 연결 실패를 할 수 있다. 실무에서는 재시도 설정, healthcheck, wait 스크립트 등을 함께 고려하기도 한다.

6️⃣ mysql 서비스

mysql:
  image: mysql:8.0
 

image는 사용할 Docker 이미지를 지정한다.

여기서는 Docker Hub에 있는 공식 MySQL 8.0 이미지를 사용한다.

 

Spring Boot 애플리케이션은 직접 만든 이미지가 필요하므로 build를 사용했고, MySQL은 이미 공식 이미지가 있으므로 image를 사용했다.

7️⃣ MySQL 환경 변수

environment:
  MYSQL_ROOT_PASSWORD: root_password
  MYSQL_DATABASE: app_db
  MYSQL_USER: app_user
  MYSQL_PASSWORD: app_password
 

MySQL 공식 이미지는 환경 변수를 통해 초기 설정을 할 수 있다.

 

위 설정은 다음 의미다.

root 비밀번호: root_password
생성할 데이터베이스: app_db
생성할 사용자: app_user
사용자 비밀번호: app_password
 

컨테이너가 처음 실행될 때 이 값들을 기준으로 데이터베이스와 사용자가 생성된다.

8️⃣ volumes

volumes:
  - mysql-data:/var/lib/mysql
 

볼륨은 컨테이너 데이터를 보존하기 위해 사용한다.

MySQL 데이터는 컨테이너 내부의 /var/lib/mysql에 저장된다.

 

그런데 컨테이너를 삭제하면 내부 데이터도 함께 사라질 수 있다. 데이터베이스에서 이는 매우 위험하다.

 

그래서 Docker Volume을 연결한다.

mysql-data 볼륨
→ MySQL 컨테이너의 /var/lib/mysql에 연결
 

이렇게 하면 MySQL 컨테이너를 지우고 다시 만들어도 데이터는 볼륨에 남아 있을 수 있다.

아래쪽의 이 부분은 사용할 볼륨을 선언한 것이다.

volumes:
  mysql-data:
 

Docker compose 실행하기

이제 Spring Boot jar 파일을 먼저 빌드한다.

 

Gradle 기준으로 다음 명령어를 실행한다.

./gradlew clean build -x test
 

그다음 Docker Compose를 실행한다.

docker compose up
 

백그라운드에서 실행하려면 -d 옵션을 붙인다.

docker compose up -d
 

이 명령어를 실행하면 Compose가 compose.yml 파일을 읽고 필요한 컨테이너를 실행한다.

mysql 컨테이너 실행
spring-app 이미지 빌드
spring-app 컨테이너 실행
네트워크 생성
볼륨 생성
포트 연결
환경 변수 주입
 

실행 중인 컨테이너는 다음 명령어로 확인한다.

docker compose ps
 

로그를 확인하려면 다음 명령어를 사용한다.

docker compose logs
 

특정 서비스 로그만 보고 싶다면 서비스 이름을 붙인다.

docker compose logs app

Docker compose 중지와 삭제

실행 중인 컨테이너를 중지하려면 다음 명령어를 사용한다.

docker compose down
 

이 명령어는 Compose로 실행한 컨테이너와 네트워크를 정리한다.

하지만 기본적으로 볼륨은 삭제하지 않는다.

 

MySQL 데이터까지 완전히 삭제하고 싶다면 -v 옵션을 사용한다.

docker compose down -v
 

주의해야 한다.

docker compose down -v
 

이 명령어는 볼륨까지 삭제하므로 MySQL 데이터도 사라질 수 있다. 개발 환경에서는 괜찮을 수 있지만, 운영 환경에서는 매우 조심해야 한다.


Docker Compose 주요 명령어

Docker Compose에서 자주 사용하는 명령어는 다음과 같다.

명령어 설명
docker compose up compose.yml에 정의된 서비스 실행
docker compose up -d 백그라운드에서 실행
docker compose down 컨테이너와 네트워크 중지 및 삭제
docker compose ps 실행 중인 서비스 확인
docker compose logs 전체 로그 확인
docker compose logs app 특정 서비스 로그 확인
docker compose build 이미지 빌드
docker compose restart 서비스 재시작
docker compose exec app sh 실행 중인 컨테이너 내부 접속

예를 들어 Spring Boot 컨테이너 내부로 들어가고 싶다면 다음처럼 실행할 수 있다.

docker compose exec app sh
 

MySQL 컨테이너에 접속하고 싶다면 다음처럼 실행할 수 있다.

docker compose exec mysql mysql -u app_user -p

 Docker Compose 네트워크?

Docker Compose는 기본적으로 하나의 네트워크를 자동으로 만들어준다.

 

그래서 같은 compose.yml 안에 정의된 서비스들은 서로 서비스 이름으로 통신할 수 있다.

 

예를 들어 다음 서비스가 있다고 해보자.

services:
  app:
    ...
  mysql:
    ...
 

그러면 app 컨테이너는 MySQL에 접속할 때 다음 주소를 사용할 수 있다.

mysql:3306
 

여기서 mysql은 서비스 이름이다.

이 구조 덕분에 컨테이너 IP를 직접 알 필요가 없다. 컨테이너가 재시작되어 IP가 바뀌어도 서비스 이름으로 접근할 수 있다.

 

비유하면 Docker Compose의 서비스 이름은 내부 DNS 이름과 비슷하다.

mysql이라는 이름을 부르면
Docker Compose 네트워크 안에서 MySQL 컨테이너를 찾아준다.

 Docker Compose와 환경 변수 파일

환경 변수가 많아지면 compose.yml에 모두 작성하기 부담스러울 수 있다.

 

이때 .env 파일을 사용할 수 있다.

예를 들어 .env 파일을 만든다.

MYSQL_ROOT_PASSWORD=root_password
MYSQL_DATABASE=app_db
MYSQL_USER=app_user
MYSQL_PASSWORD=app_password
 

그리고 compose.yml에서 다음처럼 사용할 수 있다.

services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
 

이렇게 하면 민감한 값이나 환경별 설정을 파일로 분리할 수 있다.

다만 .env 파일에는 비밀번호가 들어갈 수 있으므로 Git에 올리지 않도록 주의해야 한다.

.gitignore에 다음을 추가하는 것이 좋다.

.env

 Docker Compose는 언제 사용할까?

Docker Compose는 특히 개발 환경에서 많이 사용한다.

 

예를 들어 백엔드 개발자가 프로젝트를 실행해야 한다고 해보자.

 

Docker Compose가 없다면 MySQL을 설치하고, Redis를 설치하고, 포트를 맞추고, 계정을 만들고, 설정을 하나씩 맞춰야 한다.

Docker Compose가 있으면 다음 명령어 하나로 필요한 환경을 실행할 수 있다.

docker compose up -d
 

그래서 개발 환경 구성에 매우 유용하다.

 

대표적인 사용 사례는 다음과 같다.

Spring Boot + MySQL 개발 환경
Node.js + Redis 개발 환경
Nginx + WAS + DB 로컬 테스트
메시지 큐 포함 통합 테스트
여러 마이크로서비스 로컬 실행
 

또 간단한 내부 서비스나 테스트 서버에서도 Compose를 사용할 수 있다.

 

다만 대규모 운영 환경에서는 Docker Compose보다 Kubernetes 같은 오케스트레이션 도구를 사용하는 경우가 많다.


Docker Compose와 Kubernetes의 차이

Docker Compose를 공부하다 보면 Kubernetes와도 비교하게 된다.

 

간단히 말하면 Docker Compose는 비교적 단순한 환경에서 여러 컨테이너를 실행하기 좋고, Kubernetes는 대규모 운영 환경에서 컨테이너를 자동으로 관리하기 위한 도구다.

구분 Docker Compose Kubernetes
목적 여러 컨테이너를 간단히 실행 컨테이너 운영 자동화
사용 난이도 비교적 쉽다 상대적으로 어렵다
주 사용처 로컬 개발, 테스트, 소규모 배포 대규모 운영 환경
기능 컨테이너 실행, 네트워크, 볼륨 관리 자동 복구, 스케일링, 롤링 업데이트 등
설정 파일 compose.yml YAML 매니페스트

처음 컨테이너 기반 개발 환경을 구성할 때는 Docker Compose부터 배우는 것이 좋다.


그다음 서비스 규모가 커지고 자동 배포, 자동 복구, 스케일링이 필요해지면 Kubernetes를 공부하면 좋다고 한다.


 전체 흐름 한 번에 정리하기

Spring Boot와 MySQL을 Docker Compose로 실행하는 흐름은 다음과 같다.

1. Spring Boot 애플리케이션 Dockerfile을 작성한다.
2. compose.yml에 app 서비스와 mysql 서비스를 정의한다.
3. app 서비스는 Dockerfile로 이미지를 빌드한다.
4. mysql 서비스는 mysql:8.0 이미지를 사용한다.
5. Spring Boot는 mysql이라는 서비스 이름으로 DB에 접속한다.
6. docker compose up -d 명령어로 전체 서비스를 실행한다.
7. docker compose down 명령어로 전체 서비스를 종료한다.
 

핵심 파일은 다음 두 개다.

Dockerfile
compose.yml
 

Dockerfile은 Spring Boot 이미지를 만드는 파일이다.

FROM eclipse-temurin:17-jre
WORKDIR /app
COPY build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
 

compose.yml은 Spring Boot와 MySQL을 함께 실행하는 파일이다.

services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/app_db
      SPRING_DATASOURCE_USERNAME: app_user
      SPRING_DATASOURCE_PASSWORD: app_password
    depends_on:
      - mysql

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: app_password
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:
 

실행 명령어는 다음과 같다.

./gradlew clean build -x test
docker compose up -d
 

종료 명령어는 다음과 같다.

docker compose down