Docker Compose 로컬 개발환경 구축 방법: Spring Boot, MySQL, Redis 예제로 이해하기

Docker Compose로 로컬 개발환경을 구성하는 방법을 Spring Boot, MySQL, Redis 예제로 설명합니다. 개발 서버, DB, 캐시 서버를 한 번에 실행하고 팀원 간 환경 차이를 줄이는 실무 설정 방법을 정리했습니다.

Docker Compose 로컬 개발환경 구축 방법: Spring Boot, MySQL, Redis 예제로 이해하기

Docker Compose 로컬 개발환경은 개발 서버, 데이터베이스, Redis 같은 외부 의존 서비스를 한 번에 실행하고 관리할 수 있게 해주는 실무적인 개발 방식입니다. 이 글에서는 Docker Compose를 사용해 로컬 개발환경을 구성하는 이유, 기본 구조, docker-compose.yml 작성 방법, Spring Boot와 MySQL, Redis를 함께 실행하는 예제까지 정리합니다.

Docker Compose 로컬 개발환경이 필요한 이유

개발을 하다 보면 다음과 같은 문제가 자주 발생합니다.

문제 상황설명
개발자마다 DB 버전이 다름 MySQL 5.7, 8.0 차이로 쿼리 오류 발생
Redis, DB 설치 과정이 번거로움 신규 개발자가 환경 구성에 많은 시간 사용
로컬과 서버 환경 차이 로컬에서는 되는데 서버에서는 안 되는 문제 발생
프로젝트 실행 순서 복잡 DB 실행 후 백엔드 실행 등 순서 관리 필요

Docker Compose를 사용하면 이런 문제를 줄일 수 있습니다.

 
docker compose up -d
 

위 명령어 하나로 개발에 필요한 서비스를 한 번에 실행할 수 있습니다.

Docker Compose란?

Docker Compose는 여러 개의 Docker 컨테이너를 하나의 설정 파일로 관리하는 도구입니다.

일반 Docker 명령어로 MySQL을 실행하려면 다음처럼 작성해야 합니다.

 
docker run --name mysql \
  -e MYSQL_ROOT_PASSWORD=1234 \
  -e MYSQL_DATABASE=app \
  -p 3306:3306 \
  -d mysql:8.0
 

하지만 Docker Compose를 사용하면 설정을 파일로 저장할 수 있습니다.

 
services:
  mysql:
    image: mysql:8.0
    ports:
      - "3306:3306"
 

이 방식의 장점은 명확합니다.

개발환경 설정을 코드처럼 관리할 수 있고, Git에 올려서 팀원과 공유할 수 있습니다. 또한 프로젝트를 처음 받은 개발자도 동일한 환경을 빠르게 구성할 수 있습니다.

Docker Compose 기본 파일 구조

일반적으로 프로젝트 루트에 다음 파일을 둡니다.

 
my-project/
├── docker-compose.yml
├── Dockerfile
├── src/
├── build.gradle
└── README.md
 

여기서 핵심 파일은 docker-compose.yml입니다.

MySQL만 실행하는 Docker Compose 예제

먼저 가장 기본적인 MySQL 로컬 개발환경 예제입니다.

 
services:
  mysql:
    image: mysql:8.0
    container_name: local-mysql
    restart: always
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root1234
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: app_pass
    volumes:
      - mysql_data:/var/lib/mysql
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci

volumes:
  mysql_data:
 

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

 
docker compose up -d
 

컨테이너 상태 확인은 다음 명령어를 사용합니다.

 
docker compose ps
 

로그 확인은 다음과 같이 합니다.

 
docker compose logs -f mysql
 

Spring Boot, MySQL, Redis 로컬 개발환경 예제

실무에서는 백엔드 애플리케이션, DB, Redis를 함께 사용하는 경우가 많습니다.

 
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: local-spring-app
    ports:
      - "8080:8080"
    environment:
      SPRING_PROFILES_ACTIVE: local
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/app_db?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
      SPRING_DATASOURCE_USERNAME: app_user
      SPRING_DATASOURCE_PASSWORD: app_pass
      SPRING_REDIS_HOST: redis
      SPRING_REDIS_PORT: 6379
    depends_on:
      - mysql
      - redis

  mysql:
    image: mysql:8.0
    container_name: local-mysql
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root1234
      MYSQL_DATABASE: app_db
      MYSQL_USER: app_user
      MYSQL_PASSWORD: app_pass
    volumes:
      - mysql_data:/var/lib/mysql
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci

  redis:
    image: redis:7
    container_name: local-redis
    ports:
      - "6379:6379"

volumes:
  mysql_data:
 

여기서 중요한 부분은 컨테이너 간 통신입니다.

Spring Boot 컨테이너에서 MySQL에 접근할 때 localhost를 사용하면 안 됩니다.

 
spring.datasource.url=jdbc:mysql://localhost:3306/app_db
 

Docker Compose 내부에서는 서비스 이름을 호스트명처럼 사용해야 합니다.

 
spring.datasource.url=jdbc:mysql://mysql:3306/app_db
spring.redis.host=redis
 

즉, mysql, redis는 docker-compose.yml에 작성한 서비스 이름입니다.

Spring Boot용 Dockerfile 예제

Gradle 기반 Spring Boot 프로젝트라면 다음처럼 작성할 수 있습니다.

 
FROM eclipse-temurin:17-jdk

WORKDIR /app

COPY build/libs/*.jar app.jar

EXPOSE 8080

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

빌드 후 실행합니다.

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

application-local.yml 예제

로컬 전용 설정 파일을 따로 두면 관리가 편합니다.

 
spring:
  datasource:
    url: jdbc:mysql://mysql:3306/app_db?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
    username: app_user
    password: app_pass
    driver-class-name: com.mysql.cj.jdbc.Driver

  data:
    redis:
      host: redis
      port: 6379

  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        format_sql: true
    show-sql: true
 

로컬에서 IDE로 Spring Boot를 직접 실행하고 MySQL, Redis만 Docker로 띄우는 방식도 많이 사용합니다. 이 경우에는 DB 주소를 localhost로 사용해야 합니다.

 
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/app_db?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
 

정리하면 다음과 같습니다.

실행 방식DB Host
Spring Boot도 Docker 컨테이너에서 실행 mysql
Spring Boot는 IDE에서 실행, DB만 Docker 실행 localhost

자주 사용하는 Docker Compose 명령어

 
docker compose up -d
 

컨테이너를 백그라운드로 실행합니다.

 
docker compose down
 

컨테이너를 종료하고 네트워크를 제거합니다.

 
docker compose down -v
 

컨테이너와 볼륨까지 삭제합니다. MySQL 데이터도 삭제되므로 주의해야 합니다.

 
docker compose logs -f
 

전체 서비스 로그를 확인합니다.

 
docker compose logs -f app
 

특정 서비스 로그만 확인합니다.

 
docker compose restart
 

전체 서비스를 재시작합니다.

 
docker compose exec mysql bash
 

MySQL 컨테이너 내부로 접속합니다.

Docker Compose 사용 시 자주 발생하는 오류

1. MySQL 연결 실패

대표적인 오류입니다.

Communications link failure
Connection refused
 

주요 원인은 다음과 같습니다.

원인해결 방법
DB 컨테이너가 아직 준비되지 않음 healthcheck 추가
DB 주소를 localhost로 설정 Compose 내부에서는 mysql 사용
포트 충돌 로컬 3306 사용 여부 확인
계정 정보 불일치 environment 값 확인

2. 포트 충돌 오류

Bind for 0.0.0.0:3306 failed: port is already allocated
 

이미 로컬 PC에서 MySQL이 실행 중일 때 발생합니다.

해결 방법은 포트를 변경하는 것입니다.

 
ports:
  - "3307:3306"
 

이 경우 로컬에서는 3307로 접속합니다.

 
jdbc:mysql://localhost:3307/app_db
 

3. 데이터가 계속 남아 있는 문제

docker compose down을 해도 MySQL 데이터가 남아 있다면 볼륨 때문입니다.

 
docker compose down -v
 

볼륨까지 삭제하면 초기 상태로 다시 시작할 수 있습니다.

실무에서 추천하는 Docker Compose 구성 방식

로컬 개발환경에서는 모든 것을 Docker로 실행할 수도 있지만, 반드시 그래야 하는 것은 아닙니다.

실무에서는 보통 다음 방식을 많이 사용합니다.

구성 방식추천 상황
DB, Redis만 Docker 실행 일반적인 백엔드 개발
App, DB, Redis 모두 Docker 실행 배포 환경과 최대한 비슷하게 테스트
Nginx까지 포함 프론트엔드, 백엔드 프록시 테스트
Kafka, Elasticsearch 포함 대규모 서비스 로컬 테스트

개발 속도를 중요하게 본다면 Spring Boot는 IDE에서 실행하고, MySQL과 Redis만 Docker Compose로 띄우는 방식이 편합니다.

.env 파일로 환경변수 분리하기

비밀번호나 포트는 docker-compose.yml에 직접 쓰기보다 .env로 분리할 수 있습니다.

 
MYSQL_ROOT_PASSWORD=root1234
MYSQL_DATABASE=app_db
MYSQL_USER=app_user
MYSQL_PASSWORD=app_pass
MYSQL_PORT=3306
REDIS_PORT=6379
 

docker-compose.yml에서는 다음처럼 사용합니다.

 
services:
  mysql:
    image: mysql:8.0
    ports:
      - "${MYSQL_PORT}:3306"
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}

  redis:
    image: redis:7
    ports:
      - "${REDIS_PORT}:6379"
 

단, 실제 운영용 비밀번호를 .env에 넣고 Git에 올리면 안 됩니다.

.gitignore에 추가하는 것이 좋습니다.

 
.env
 

대신 예시 파일을 제공합니다.

 
.env.example
 

FAQ

Docker Compose와 Dockerfile은 무엇이 다른가요?

Dockerfile은 하나의 이미지를 만드는 설정 파일입니다. Docker Compose는 여러 컨테이너를 함께 실행하는 설정 파일입니다.

Docker Compose에서 localhost가 안 되는 이유는 무엇인가요?

컨테이너 내부의 localhost는 내 PC가 아니라 해당 컨테이너 자신을 의미합니다. Compose 네트워크 안에서는 서비스 이름으로 다른 컨테이너에 접근해야 합니다.

로컬 개발환경에서 DB 데이터는 어디에 저장되나요?

volumes 설정을 사용하면 Docker 볼륨에 저장됩니다. 그래서 컨테이너를 삭제해도 데이터가 유지될 수 있습니다.

Docker Compose 파일을 Git에 올려도 되나요?

올려도 됩니다. 오히려 팀 개발에서는 권장됩니다. 다만 실제 비밀번호, API Key, 운영 DB 정보는 포함하면 안 됩니다.

마무리

Docker Compose 로컬 개발환경을 사용하면 MySQL, Redis, 백엔드 애플리케이션을 일관된 방식으로 실행할 수 있습니다. 특히 팀 프로젝트에서는 개발자마다 다른 환경 때문에 발생하는 오류를 줄이고, 신규 개발자가 빠르게 프로젝트를 실행할 수 있다는 장점이 있습니다.

처음에는 MySQL이나 Redis 같은 외부 서비스부터 Docker Compose로 관리하고, 이후 필요에 따라 Spring Boot, Nginx, Kafka, Elasticsearch 등을 추가하는 방식으로 확장하는 것이 좋습니다.

 

Docker Compose, Docker 로컬 개발환경, 도커 컴포즈, Spring Boot Docker, MySQL Docker, Redis Docker, 개발환경 구성, docker-compose.yml, 백엔드 개발환경, 로컬 서버 구축