본문 바로가기

Backend/Study

[DevOps] Docker Compose로 개발 환경 빠르게 세팅하기

반응형

0: 개요

Docker Compose를 활용해 로컬 개발 환경을 몇 분 만에 구성하는 방법을 설명합니다. 백엔드/프론트엔드/DB/캐시를 한 번에 올리는 Compose 예제, .env 관리, 볼륨/네트워크, healthcheck & depends_on, 프로파일(profiles), 오버라이드 파일, 핫 리로드, 트러블슈팅까지 실무 포인트를 담았습니다.

1. 왜 Docker Compose인가?

  • 원클릭(원커맨드) 부팅: docker compose up -d 한 번으로 모든 서비스 실행
  • 개발-테스트 일관성: 팀원/CI 환경이 동일한 스택 사용
  • 격리된 네트워크: 서비스명으로 안정적 통신(DB_HOST=mysql)
  • 빠른 재현: 버그 재현/시나리오 테스트에 최적

2. 핵심 개념 한눈에

개념 설명 예시
services 컨테이너 집합 backend, frontend, mysql, redis
volumes 데이터/코드 공유 .:/app, db-data:/var/lib/mysql
networks 컨테이너 간 DNS 서비스명으로 통신(mysql:3306)
env 환경 변수/비밀 관리 .env, environment:
healthcheck 준비 상태 판단 mysqladmin ping
depends_on 기동 순서/대기 condition: service_healthy
profiles 선택적 서비스 profiles: [dev]

3. 5분 만에 끝내는 빠른 시작 (백엔드+프론트+MySQL+Redis)

1) 폴더 구조

project/
├─ docker-compose.yml
├─ .env
├─ backend/       # Spring Boot or Node.js
├─ frontend/      # React/Vite/Next
└─ init/          # DB 초기 스키마/더미 데이터(sql)

2) .env (개발용)

MYSQL_DATABASE=appdb
MYSQL_USER=appuser
MYSQL_PASSWORD=apppass
MYSQL_ROOT_PASSWORD=rootpass
DB_HOST=mysql
DB_PORT=3306
REDIS_HOST=redis
REDIS_PORT=6379
BACKEND_PORT=8080
FRONTEND_PORT=5173

3) docker-compose.yml

version: "3.8"

services:
  mysql:
    image: mysql:8.0
    container_name: mysql
    environment:
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    ports: ["3306:3306"]
    volumes:
      - db-data:/var/lib/mysql
      - ./init:/docker-entrypoint-initdb.d
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD --silent"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s
    networks: [app-net]

  redis:
    image: redis:7-alpine
    container_name: redis
    ports: ["6379:6379"]
    command: ["redis-server", "--appendonly", "yes"]
    networks: [app-net]

  backend:
    build: ./backend
    container_name: backend
    ports: ["${BACKEND_PORT}:8080"]
    environment:
      DB_HOST: ${DB_HOST}
      DB_PORT: ${DB_PORT}
      DB_NAME: ${MYSQL_DATABASE}
      DB_USER: ${MYSQL_USER}
      DB_PASSWORD: ${MYSQL_PASSWORD}
      REDIS_HOST: ${REDIS_HOST}
      REDIS_PORT: ${REDIS_PORT}
    volumes:
      - ./backend:/app
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_started
    networks: [app-net]

  frontend:
    build: ./frontend
    container_name: frontend
    ports: ["${FRONTEND_PORT}:5173"]
    environment:
      VITE_API_URL: http://localhost:${BACKEND_PORT}
    volumes:
      - ./frontend:/app
    depends_on:
      backend:
        condition: service_started
    networks: [app-net]
    profiles: ["dev"]  # 필요할 때만 올리기

volumes:
  db-data:

networks:
  app-net:
    driver: bridge

실행: docker compose up -d백엔드(http://localhost:8080), 프론트(http://localhost:5173)


4. 코드 변경 즉시 반영: 핫 리로드

  • Node.js: nodemon 또는 tsx --watch 사용, volumes로 소스 마운트
  • Spring Boot: spring-boot-devtools 추가 + IDE 자동 빌드, 또는 JRebel
  • React/Vite: vite dev 서버 실행, volumes 마운트

예) Node.js Dockerfile (개발용)

# backend/Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 8080
CMD ["npm", "run", "dev"]  # nodemon / tsx watch

예) Spring Boot Dockerfile (개발용)

# backend/Dockerfile
FROM eclipse-temurin:21-jdk
WORKDIR /app
COPY .mvn .mvn
COPY mvnw pom.xml ./
RUN ./mvnw -q -DskipTests dependency:go-offline
COPY src ./src
EXPOSE 8080
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=local"]

5. Healthcheck & depends_on로 안정 부팅

DB가 준비되기 전에 앱이 먼저 올라오면 연결 실패가 납니다. healthcheckdepends_on: condition: service_healthy를 사용하면 앱이 DB 준비를 기다립니다.

depends_on:
  mysql:
    condition: service_healthy

6. profiles / override 파일로 유연하게

1) profiles

# 특정 서비스만 선택적으로 기동
docker compose --profile dev up -d
docker compose --profile dev down

2) override 파일

docker-compose.override.yml은 자동 병합됩니다(로컬 개발 전용 설정 등).

# docker-compose.override.yml (예시)
services:
  backend:
    environment:
      LOG_LEVEL: debug
    extra_hosts:
      - "host.docker.internal:host-gateway"

7. 유용한 명령 모음

# 상태/로그/셸
docker compose ps
docker compose logs -f backend
docker compose exec mysql bash

# 정리
docker compose down -v      # 볼륨 포함 제거(주의!)
docker system prune -af     # 강력 정리(신중히)

8. 트러블슈팅 체크리스트

  • 연결 안 됨: 서비스명으로 접근했는지 확인 (DB_HOST=mysql, localhost 금지)
  • DB 준비 전 앱 기동: healthcheck & depends_on 설정
  • .env 적용 안 됨: docker compose config로 실제 값 확인
  • 포트 충돌: lsof -i :포트로 점유 확인 후 변경
  • 파일 변경 미반영: volumes 마운트/감시 도구 설정(nodemon/devtools) 확인

9. 캐시/속도 최적화 (빌드 및 런타임)

  • Dockerfile 계층 최적화: 의존성 설치를 소스 복사 전에 실행(package.jsonnpm ciCOPY . .)
  • 멀티스테이지: 빌드와 런타임 이미지를 분리해 용량↓
  • 볼륨 전략: DB 데이터는 네임드 볼륨 사용(db-data)
  • 공유 네트워크: 팀/다른 compose와 통신이 필요하면 사전에 docker network create로 외부 네트워크 구성

10. 보너스: Makefile로 원커맨드 자동화

up:
\tdocker compose up -d
down:
\tdocker compose down
logs:
\tdocker compose logs -f --tail=200
rebuild:
\tdocker compose build --no-cache && docker compose up -d

11. 요약

  • Compose로 DB/캐시/백엔드/프론트를 한 번에 올린다
  • .env로 환경 변수 표준화, volumes로 핫 리로드
  • healthcheck + depends_on으로 안정된 부팅
  • profiles/override로 상황별 구성 제어

한 줄 정리: “docker compose up -d” 한 번으로 팀 전체 개발 환경을 일관되게!

반응형