Docker

도커(Docker) compose 사용법

10Biliion 2025. 5. 19. 15:07

 

Docker Compose란?

Docker Compose여러 개의 컨테이너를 번에 정의하고 실행있는 도구입니다. docker-compose.yml 파일 하나로 여러 서비스를 정의할 있으며, 개발/테스트 환경에서 매우 유용합니다.


Compose 기본 구조

version: '3.8'
services:
  서비스명:
    image: 사용할 이미지
    ports: 
      - "로컬포트:컨테이너포트"
    environment:
      - 환경변수=값
    depends_on:
      - 다른서비스

 

Spring Boot + MySQL 연결

Spring Boot 애플리케이션이 MySQL 데이터베이스에 접근하는 예제를 Compose구성해보겠습니다.

1. docker-compose.yml

version: '3.8'

services:
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root1234
      MYSQL_DATABASE: mydb
    ports:
      - "3306:3306"
    volumes:
      - ./mysql_data:/var/lib/mysql

  spring:
    build: .
    depends_on:
      - db
    ports:
      - "8080:8080"

2. Spring Boot application.yml 또는 application.properties

spring:
  datasource:
    url: jdbc:mysql://db:3306/mydb
    username: user
    password: user1234
    driver-class-name: com.mysql.cj.jdbc.Driver

여기서 핵심은 **DB 접속 주소가 localhost가 아닌 db**라는 점입니다. 이건 Compose에서 설정한 서비스명을 기반으로 내부 DNS가 연결되기 때문입니다.


연결이 안 되는 이유

잘못된 JDBC URL

# ❌ 이렇게 하면 안 됩니다 (로컬 DB 기준)
spring.datasource.url=jdbc:mysql://localhost:3306/mydb

컨테이너 안에서 실행되는 애플리케이션은 localhost자기 자신으로 인식합니다. 그래서 localhostDB찾고, 반드시 Compose의 **서비스명(db)**사용해야 합니다.


DB완전히 뜨기 전에 애플리케이션이 먼저 실행됨

Spring Boot 컨테이너가 MySQL완전히 시작되기 전에 실행될 경우 Connection refused, Communications link failure 등의 오류가 발생합니다.

해결 방법:

  • depends_on 사용 (단, 순서만 보장하고, 준비 완료는 보장 함)
  • Spring Boot에서 spring.datasource.initialization-mode=alwaysretry 로직 추가
  • wait-for-it.sh, dockerize, initContainers 등으로 DB 준비 확인

 

Spring BootMySQL연결을 시도하면서 다음과 같은 오류가 난다면?

com.mysql.cj.jdbc.exceptions.CommunicationsException:
Communications link failure

실행 순서를 맞췄는데 실패할까?

답은 depends_on한계있습니다.

  • depends_on컨테이너 시작 순서만 보장합니다.
  • 서비스 준비 완료(=DB 접속 가능) 상태까지는 보장하지 않습니다.

즉, MySQL 컨테이너가 시작만 됐지,
3306 포트가 완전히 열리고, DB가 초기화되고, 사용자 계정 생성되고모든 끝난 상태는 아닙니다.

그래서 Spring Boot너무 빨리 DB연결 시도하면,
아직 준비되지 않은 MySQL접근하게 되고 연결 실패발생합니다.


해결책: healthcheck + condition: service_healthy

🧩 Spring + MySQL + Redis 연결

services:
  my-server:
    build: .
    ports:
      - 8080:8080
    depends_on:
      my-db:
        condition: service_healthy
      my-cache-server:
        condition: service_healthy

  my-db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: password123
      MYSQL_DATABASE: mydb
    volumes:
      - ./mysql_data:/var/lib/mysql
    ports:
      - 3306:3306
    healthcheck:
      test: [ "CMD", "mysqladmin", "ping"]
      interval: 5s
      retries: 10

  my-cache-server:
    image: redis
    ports:
      - 6379:6379
    healthcheck:
      test: [ "CMD", "redis-cli", "ping" ]
      interval: 5s
      retries: 10

 

이제는 DB진짜 접속 가능할 때까지 Spring 앱이 기다렸다가 실행됩니다.

항목 설명
depends_on 컨테이너 시작 순서만 보장
healthcheck 컨테이너의 정상 작동 상태 판단
condition: service_healthy 의존 서비스가 완전히 준비될 때까지 실행 대기

Docker Compose로 실행하기

docker-compose up --build

// --build는 docker-compose up을 실행할 때, 명시적으로 이미지를 새로 빌드하도록 지시

컨테이너가 실행됩니다:

  • spring-app: Spring Boot 애플리케이션
  • mysql-db: MySQL 데이터베이스

접속 테스트

정상 연결되면 로그에 다음과 같은 메시지가 출력됩니다:

Connected to database: mydb

또는 애플리케이션에서 정상적으로 데이터 조회 저장이 이뤄질 있습니다.


프로젝트 구조 예시

myproject/
├── docker-compose.yml
├── Dockerfile
├── src/
└── build.gradle or pom.xml

 

 

문제 원인 해결 방법
DB 연결 오류 JDBC URL에서 localhost 사용 서비스명 (db) 사용
Connection refused DB준비되기 전에 Spring 실행 depends_on + retry 로직
DB 접속 오류 환경변수 누락 또는 잘못된 비밀번호 docker-compose.yml설정 파일 싱크 확인
 

📚 참고 자료