G: 안녕하세요! 👋 복잡한 애플리케이션 개발 환경 설정 때문에 머리 아프셨던 경험, 다들 있으실 겁니다. 웹 서버, 데이터베이스, 캐시, 백엔드 서비스 등 여러 컴포넌트가 얽히면 관리하기가 여간 까다로운 게 아니죠. 🤯
하지만 걱정 마세요! Docker Compose가 바로 이 문제를 해결해 줄 마법 같은 도구입니다. Docker Compose를 사용하면 여러 개의 컨테이너를 하나로 묶어 쉽고 일관되게 관리할 수 있습니다. 마치 오케스트라의 지휘자처럼, 모든 컨테이너를 조화롭게 움직이게 할 수 있죠! 🎼
이 가이드에서는 Docker Compose의 핵심 명령어들을 깊이 있게 파헤쳐 보고, 실제 예시와 함께 어떻게 활용할 수 있는지 완벽하게 설명해 드릴게요. 이 글을 다 읽고 나면 여러분은 멀티 컨테이너 환경의 베테랑이 되어 있을 겁니다! 🚀
📚 목차
- Docker Compose란 무엇인가요?
docker-compose.yml
: 모든 것의 시작점- 핵심 Docker Compose 명령어 파헤치기
docker-compose up
: 컨테이너 띄우기 (그리고 더 많은 기능!)docker-compose down
: 깨끗하게 종료하기docker-compose ps
: 현재 상태 확인하기docker-compose logs
: 컨테이너 로그 보기docker-compose exec
: 실행 중인 컨테이너에 접속하기docker-compose build
: 이미지 직접 빌드하기docker-compose stop
,start
,restart
: 컨테이너 제어하기docker-compose rm
: 컨테이너 제거하기docker-compose config
: 설정 유효성 검사 및 보기docker-compose run
: 일회성 명령어 실행하기
- Docker Compose 활용 팁 & 베스트 프랙티스
- 마무리하며
1. Docker Compose란 무엇인가요?
Docker Compose는 다중 컨테이너 Docker 애플리케이션을 정의하고 실행하기 위한 도구입니다. 📦📦📦
쉽게 말해, 웹 애플리케이션을 개발할 때 웹 서버 (Nginx), 애플리케이션 서버 (Node.js/Python), 데이터베이스 (PostgreSQL/MySQL), 캐시 (Redis) 등 여러 개의 컨테이너가 필요하잖아요? 이 모든 컨테이너를 개별적으로 docker run
명령어로 실행하고 연결하는 것은 매우 번거롭습니다.
Docker Compose는 이 모든 과정을 하나의 YAML 파일(docker-compose.yml
)로 정의하고, 단일 명령어로 한 번에 빌드, 실행, 연결, 종료할 수 있게 해줍니다. 마치 레시피 하나로 복잡한 요리를 한 번에 완성하는 것과 같아요! 👩🍳
💡 왜 중요할까요?
- 간편한 환경 설정: 복잡한 개발 환경을 몇 줄의 코드로 정의하고 공유할 수 있습니다.
- 일관된 개발 환경: 팀원 모두가 동일한 환경에서 작업할 수 있어 “내 컴퓨터에서는 되는데…” 문제를 줄여줍니다.
- 빠른 시작/종료: 애플리케이션 스택을 통째로 쉽게 시작하고 중단할 수 있습니다.
- 유지보수 용이성: 컨테이너 간의 의존성, 네트워크 설정 등을 한눈에 파악하고 관리할 수 있습니다.
참고: 최신 Docker Desktop 버전에서는 docker-compose
명령 대신 docker compose
(띄어쓰기) 명령을 권장하고 있습니다. 기능은 동일하며, 이 가이드에서는 전통적인 docker-compose
를 기준으로 설명하지만, docker compose
로 대체해서 사용하셔도 무방합니다.
2. docker-compose.yml
: 모든 것의 시작점
Docker Compose를 사용하려면 먼저 docker-compose.yml
파일을 작성해야 합니다. 이 파일은 Docker Compose에게 “어떤 컨테이너를 만들고, 어떻게 연결하고, 어떤 설정을 사용할지” 알려주는 설계도와 같습니다. 📝
간단한 docker-compose.yml
예시: Nginx와 간단한 Node.js 웹 애플리케이션, 그리고 PostgreSQL 데이터베이스
# docker-compose.yml
version: '3.8' # Docker Compose 파일 형식 버전
services: # 애플리케이션을 구성하는 서비스들 정의
web: # 웹 서비스 (Node.js 앱)
build: . # 현재 디렉토리의 Dockerfile을 사용하여 이미지 빌드
ports:
- "80:3000" # 호스트의 80번 포트를 컨테이너의 3000번 포트에 연결 (포트 포워딩)
volumes:
- .:/usr/src/app # 현재 디렉토리를 컨테이너의 /usr/src/app에 마운트 (코드 동기화)
depends_on: # 이 서비스가 시작되기 전에 db 서비스가 시작되어야 함을 명시
- db
environment: # 컨테이너 내부에서 사용할 환경 변수 설정
NODE_ENV: production
DATABASE_URL: postgres://user:password@db:5432/mydatabase
db: # 데이터베이스 서비스 (PostgreSQL)
image: postgres:13 # Docker Hub에서 postgres:13 이미지를 다운로드하여 사용
environment: # 데이터베이스 환경 변수 설정 (중요!)
POSTGRES_DB: mydatabase
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- db_data:/var/lib/postgresql/data # 데이터 영속성을 위한 볼륨 마운트 (DB 데이터 저장)
volumes: # 명시적으로 볼륨 정의 (컨테이너가 삭제되어도 데이터는 유지)
db_data:
🤔 이 YAML 파일이 의미하는 것은?
version
: 사용하려는 Docker Compose 파일의 버전입니다. 최신 기능을 위해3.8
이상을 사용하는 것이 좋습니다.services
: 이 섹션 아래에 애플리케이션을 구성하는 개별 서비스(컨테이너)를 정의합니다.web
:web
이라는 서비스입니다.build: .
: 현재 디렉토리에 있는Dockerfile
을 사용하여web
서비스의 이미지를 빌드합니다.ports
:호스트_포트:컨테이너_포트
형식으로 포트를 매핑합니다.volumes
:호스트_경로:컨테이너_경로
형식으로 디렉토리를 마운트합니다. 개발 시 코드 변경사항이 즉시 반영되도록 할 때 유용합니다.depends_on
: 서비스 간의 시작 순서를 정의합니다.web
이 시작되기 전에db
가 시작되어야 합니다.environment
: 컨테이너 내부에서 사용할 환경 변수를 설정합니다.
db
:db
라는 서비스입니다.image: postgres:13
: Docker Hub에서postgres:13
이미지를 가져와 사용합니다.build
대신image
를 사용하면 이미 빌드된 이미지를 사용하겠다는 의미입니다.environment
: 데이터베이스 초기 설정에 필요한 환경 변수들입니다.volumes
:db_data
라는 이름의 볼륨을db
컨테이너의/var/lib/postgresql/data
경로에 마운트합니다. PostgreSQL 데이터가 컨테이너가 삭제되어도 유지되도록 합니다.
volumes
:services
섹션에서 사용된db_data
와 같은 명명된 볼륨들을 정의하는 섹션입니다. 컨테이너가 사라져도 데이터가 보존되어야 할 때 주로 사용합니다.
3. 핵심 Docker Compose 명령어 파헤치기
이제 이 docker-compose.yml
파일을 가지고 어떤 명령어들을 사용할 수 있는지 알아봅시다! 🛠️
3.1. docker-compose up
: 컨테이너 띄우기 (그리고 더 많은 기능!)
가장 기본적이고 중요한 명령어입니다. docker-compose.yml
파일에 정의된 모든 서비스를 빌드하고, 생성하고, 시작합니다.
-
기본 사용법:
docker-compose up
이 명령어를 실행하면 모든 서비스의 로그가 현재 터미널에 출력됩니다. 컨테이너가 정상적으로 시작되었는지 확인하기 좋습니다.
-
백그라운드 (detached) 모드로 실행:
docker-compose up -d
-d
또는--detach
플래그를 사용하면 컨테이너들이 백그라운드에서 실행되고 터미널을 다시 사용할 수 있습니다. 서버 애플리케이션을 배포하거나 개발 중에도 터미널을 계속 사용해야 할 때 유용합니다. 👍 -
이미지 강제 재빌드:
docker-compose up --build
docker-compose.yml
파일에서build
지시어를 사용하는 서비스의 Dockerfile 내용이 변경되었을 때, 이 플래그를 사용하면 Docker 이미지를 강제로 다시 빌드합니다.Dockerfile
을 수정했다면 꼭 사용해야 합니다! 🏗️ -
컨테이너 강제 재생성:
docker-compose up --force-recreate
컨테이너의 설정(예: 환경 변수, 포트 매핑)이 변경되었지만 이미지가 바뀌지 않았을 때, 이 플래그를 사용하면 기존 컨테이너를 삭제하고 새로운 설정으로 다시 생성합니다. 때로는
--build
와 함께 사용하기도 합니다.
예시:
# 백그라운드에서 모든 서비스를 시작 (가장 흔한 사용법)
docker-compose up -d
# Dockerfile 수정 후, 이미지를 재빌드하고 서비스를 시작
docker-compose up -d --build
# 특정 서비스만 시작 (예: web 서비스만)
docker-compose up -d web
3.2. docker-compose down
: 깨끗하게 종료하기
up
명령어로 시작된 모든 서비스와 연결된 네트워크를 중지하고 제거합니다. 개발 환경을 깔끔하게 정리할 때 필수적인 명령어입니다. ✨
-
기본 사용법:
docker-compose down
이 명령어는 컨테이너와 네트워크를 제거하지만,
volumes
섹션에 정의된 명명된 볼륨(예:db_data
)이나 익명 볼륨은 제거하지 않습니다. -
볼륨까지 함께 제거:
docker-compose down --volumes # 또는 줄여서 -v docker-compose down -v
이 플래그를 사용하면
docker-compose.yml
에 정의된 명명된 볼륨(db_data
)과 익명 볼륨까지 모두 제거합니다. 데이터베이스의 데이터를 완전히 초기화하고 싶을 때 유용합니다. 주의: 데이터가 영구적으로 삭제됩니다! 🗑️ -
이미지까지 함께 제거:
docker-compose down --rmi all
컨테이너를 제거한 후, Docker Compose가 생성한 모든 이미지(
web
서비스의 빌드된 이미지 등)까지 제거합니다. 개발 환경을 완전히 초기화하고 싶을 때 사용합니다.
예시:
# 모든 컨테이너와 네트워크를 중지하고 제거
docker-compose down
# 데이터베이스 데이터까지 포함하여 모든 것을 제거 (주의!)
docker-compose down -v
3.3. docker-compose ps
: 현재 상태 확인하기
실행 중인 Docker Compose 서비스들의 현재 상태를 보여줍니다. 어떤 컨테이너가 실행 중이고, 어떤 포트가 열려 있으며, 어떤 상태인지 한눈에 확인할 수 있습니다. 👀
- 기본 사용법:
docker-compose ps
예시:
$ docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------
myproject_db_1 docker-entrypoint.sh postgres Up 5432/tcp
myproject_web_1 /bin/sh -c node index.js Up 0.0.0.0:80->3000/tcp
myproject
는 프로젝트 이름인데, 기본적으로 docker-compose.yml
파일이 있는 디렉토리 이름이 사용됩니다.
3.4. docker-compose logs
: 컨테이너 로그 보기
특정 서비스 또는 모든 서비스의 로그를 확인할 수 있습니다. 디버깅할 때 매우 유용한 명령어입니다. 🐛
-
모든 서비스 로그 보기:
docker-compose logs
-
특정 서비스 로그 보기:
docker-compose logs web
web
서비스의 로그만 보여줍니다. -
실시간 로그 확인 (follow):
docker-compose logs -f web
-f
또는--follow
플래그를 사용하면tail -f
처럼 실시간으로 로그를 계속 출력합니다. 개발 중 로그를 모니터링할 때 필수적입니다. 🕵️♂️ -
로그의 마지막 N줄만 보기:
docker-compose logs --tail 50 web
--tail
플래그를 사용하면 로그의 마지막 50줄만 보여줍니다.
예시:
# web 서비스의 실시간 로그 확인
docker-compose logs -f web
# db 서비스의 마지막 100줄 로그 확인
docker-compose logs --tail 100 db
3.5. docker-compose exec
: 실행 중인 컨테이너에 접속하기
실행 중인 서비스 컨테이너 내에서 명령어를 실행할 수 있습니다. 컨테이너 내부를 탐색하거나 특정 스크립트를 실행할 때 매우 유용합니다. 💻
-
특정 서비스 컨테이너 내부로 접속 (쉘 접근):
docker-compose exec web bash # 또는 sh, zsh 등 해당 컨테이너에 설치된 쉘
이 명령어는
web
서비스의 컨테이너 내부로 들어가 쉘 환경에 접근하게 해줍니다. 컨테이너 내부에서 파일을 확인하거나 디버깅 작업을 할 때 많이 사용합니다. -
컨테이너 내부에서 특정 명령어 실행:
docker-compose exec db psql -U user mydatabase
db
컨테이너 내부에서psql -U user mydatabase
명령어를 실행하여 PostgreSQL 데이터베이스에 접속합니다.
예시:
# web 컨테이너 안에서 npm install 실행 (만약 패키지 설치가 필요하다면)
docker-compose exec web npm install
# db 컨테이너 안에서 특정 SQL 파일 실행
docker-compose exec db sh -c "psql -U user mydatabase < /tmp/init.sql"
3.6. docker-compose build
: 이미지 직접 빌드하기
docker-compose.yml
파일에 build
지시어가 있는 서비스의 이미지를 명시적으로 빌드합니다. docker-compose up --build
와 동일한 빌드 과정을 수행하지만, 컨테이너를 시작하지 않고 이미지 빌드만 합니다.
-
기본 사용법:
docker-compose build
모든
build
지시어를 가진 서비스를 빌드합니다. -
특정 서비스만 빌드:
docker-compose build web
web
서비스의 이미지만 빌드합니다.
예시:
# 새로운 Dockerfile 변경사항을 적용하기 위해 이미지 재빌드
docker-compose build web
3.7. docker-compose stop
, start
, restart
: 컨테이너 제어하기
이 명령어들은 실행 중인 컨테이너의 상태를 제어하는 데 사용됩니다.
-
docker-compose stop
: 실행 중인 모든 서비스 또는 특정 서비스를 “우아하게” 중지합니다. 컨테이너는 중지되지만 제거되지는 않으므로, 나중에start
명령어로 다시 시작할 수 있습니다. ⏸️docker-compose stop # 모든 서비스 중지 docker-compose stop web # web 서비스만 중지
-
docker-compose start
: 이전에stop
명령어로 중지된 서비스들을 다시 시작합니다. ⏯️docker-compose start # 중지된 모든 서비스 시작 docker-compose start web # 중지된 web 서비스만 시작
-
docker-compose restart
: 실행 중인 서비스들을 중지했다가 다시 시작합니다. 컨테이너의 설정을 변경했을 때(단, 이미지 빌드가 필요 없는 경우) 유용합니다. 🔄docker-compose restart # 모든 서비스 재시작 docker-compose restart web # web 서비스만 재시작
3.8. docker-compose rm
: 컨테이너 제거하기
중지된 서비스 컨테이너를 제거합니다. docker-compose down
은 컨테이너와 네트워크를 제거하지만, rm
은 이미 중지된 개별 컨테이너를 대상으로 합니다.
-
기본 사용법:
docker-compose rm
현재 중지된 모든 컨테이너를 제거할지 확인 메시지를 띄웁니다.
-
강제 제거:
docker-compose rm -f
-f
또는--force
플래그를 사용하면 확인 메시지 없이 강제로 제거합니다.
예시:
# 중지된 모든 컨테이너를 확인 없이 강제 제거
docker-compose rm -f
3.9. docker-compose config
: 설정 유효성 검사 및 보기
docker-compose.yml
파일의 유효성을 검사하고, Docker Compose가 실제로 해석할 최종 구성을 YAML 형식으로 출력합니다. 파일을 수정했을 때 오류가 없는지 확인하거나, 디버깅할 때 유용합니다. ✅
-
기본 사용법:
docker-compose config
파일에 오류가 있다면 오류 메시지를 출력하고, 아니라면 최종 구성을 보여줍니다.
-
경고 무시:
docker-compose config -q
-q
또는--quiet
플래그는 경고만 표시하고 구성을 출력하지 않습니다. 파일 유효성만 빠르게 확인하고 싶을 때 좋습니다.
예시:
# docker-compose.yml 파일의 구성을 검증하고 출력
docker-compose config
3.10. docker-compose run
: 일회성 명령어 실행하기
docker-compose.yml
에 정의된 서비스 컨테이너와 동일한 환경에서 일회성 명령어를 실행합니다. 주로 마이그레이션 스크립트 실행, 테스트 실행, 디버깅 등에 사용됩니다. exec
와 달리 새로운 임시 컨테이너를 생성하여 명령어를 실행한 후 종료됩니다. 🏃♂️
-
기본 사용법:
docker-compose run web npm test
web
서비스의 이미지와 설정을 기반으로 새로운 컨테이너를 생성하고npm test
명령어를 실행한 후, 컨테이너를 종료합니다. -
포트 매핑 없이 실행:
docker-compose run --no-deps web bash
--no-deps
플래그는depends_on
에 정의된 다른 서비스들을 시작하지 않고 해당 서비스만 실행합니다. 필요한 경우 유용합니다.
예시:
# web 서비스 컨테이너에서 데이터베이스 마이그레이션 실행
docker-compose run web npm run db:migrate
# db 서비스 컨테이너에서 PostgreSQL 클라이언트 실행 (새로운 컨테이너로)
docker-compose run db psql -U user mydatabase
4. Docker Compose 활용 팁 & 베스트 프랙티스
-
환경 변수 관리 (
.env
파일): 민감한 정보(비밀번호, API 키 등)나 환경에 따라 달라지는 값들은docker-compose.yml
에 직접 명시하기보다.env
파일을 활용하는 것이 좋습니다.# .env 파일 예시 POSTGRES_USER=myuser POSTGRES_PASSWORD=mypassword
docker-compose.yml
에서environment
섹션에 변수 이름만 적으면 자동으로.env
파일에서 값을 가져옵니다.# docker-compose.yml services: db: environment: POSTGRES_USER: ${POSTGRES_USER} # .env 파일에서 POSTGRES_USER 값을 가져옴 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
.env
파일은 Git에 커밋하지 않도록.gitignore
에 추가하는 것이 보안상 안전합니다. 🔐 -
여러 환경을 위한 설정 (
-f
플래그): 개발, 테스트, 프로덕션 등 여러 환경에 따라docker-compose.yml
파일이 달라질 수 있습니다. 이때 여러 파일을 사용하여 관리할 수 있습니다.docker-compose.yml
(기본 설정)docker-compose.dev.yml
(개발 환경 오버라이드)docker-compose.prod.yml
(프로덕션 환경 오버라이드)# 개발 환경으로 실행 docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
프로덕션 환경으로 실행
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d
나중에 오는 파일의 설정이 이전 파일의 설정을 덮어씁니다. 겹치는 서비스 이름이 있다면요! 🔄
-
자원 제한 (
deploy
또는resources
): 컨테이너가 너무 많은 CPU나 메모리를 사용하지 않도록 제한을 걸 수 있습니다. 특히 개발 환경에서 노트북 자원을 보호할 때 유용합니다. (Docker Compose v3.x에서는deploy
섹션 아래resources
를 사용합니다)services: web: # ... deploy: resources: limits: cpus: '0.5' # 0.5 코어 제한 memory: 512M # 512MB 메모리 제한
이는 Docker Swarm 모드에서 더 강력하게 작동하며, 단일 호스트에서도 어느 정도 자원 제한을 제공합니다.
5. 마무리하며
이제 여러분은 Docker Compose의 핵심 명령어들을 완벽하게 익히셨습니다! 🎉
docker-compose up
부터 down
, ps
, logs
, exec
, run
등 다양한 명령어들을 통해 멀티 컨테이너 애플리케이션을 효율적으로 관리할 수 있게 되었을 겁니다.
Docker Compose는 복잡한 개발 환경을 단순화하고, 팀원 간의 협업을 원활하게 하며, “내 컴퓨터에서만 되는” 문제를 해결해 주는 강력한 도구입니다. 이 가이드를 통해 얻은 지식을 바탕으로 여러분의 개발 워크플로우가 훨씬 더 생산적이고 즐거워지기를 바랍니다! 😊
꾸준히 연습하고 다양한 프로젝트에 적용해 보면서 Docker Compose의 진정한 힘을 느껴보세요. 궁금한 점이나 더 알고 싶은 내용이 있다면 언제든지 댓글로 남겨주세요!
다음 글에서 또 만나요! 해피 코딩! 💻💖