G: 안녕하세요! 복잡한 멀티 컨테이너 애플리케이션을 빠르고 효율적으로 배포하고 싶으신가요? 그렇다면 Docker Compose는 여러분의 필수 도구입니다. 단일 명령어로 여러 개의 컨테이너를 한 번에 빌드하고 실행할 수 있게 해주는 마법 같은 도구죠! ✨
이 글에서는 Docker Compose를 사용하여 서비스를 배포하고 관리하는 데 필요한 핵심 명령어들을 총정리해 드릴게요. 각 명령어의 역할과 사용법을 명확한 예시와 함께 알아보고, 실전에서 바로 활용할 수 있는 꿀팁까지 알려드리겠습니다. 자, 그럼 함께 Docker Compose의 세계로 떠나볼까요? 🐳
💡 Docker Compose, 왜 필요한가요?
Docker는 컨테이너 단위로 애플리케이션을 격리하여 실행하는 강력한 도구입니다. 하지만 실제 서비스는 웹 서버, 데이터베이스, 캐시 서버 등 여러 개의 컨테이너가 유기적으로 연결되어 동작하는 경우가 대부분이죠.
이런 다중 컨테이너 애플리케이션을 수동으로 하나하나 docker run
명령어를 통해 관리하는 것은 비효율적이고 오류 발생 가능성이 높습니다. 이때 Docker Compose가 등장합니다! 👏
Docker Compose는 docker-compose.yml
이라는 YAML 파일 하나로 서비스의 구성(어떤 컨테이너들이 필요한지, 포트는 어떻게 연결할지, 볼륨은 무엇을 사용할지 등)을 정의하고, 이를 단일 명령어로 손쉽게 관리할 수 있게 해줍니다. 개발 환경 설정부터 프로덕션 배포까지, 모든 과정에서 생산성을 획기적으로 높여줄 수 있답니다.
🛠️ 시작하기 전에: docker-compose.yml
파일 이해하기
모든 Docker Compose 작업은 docker-compose.yml
(또는 docker-compose.yaml
) 파일에서 시작됩니다. 이 파일은 애플리케이션의 서비스, 네트워크, 볼륨 등을 정의하는 설계도와 같습니다.
예시를 통해 간단한 웹 애플리케이션(Node.js)과 Redis 데이터베이스를 묶어주는 docker-compose.yml
파일을 살펴보겠습니다.
# docker-compose.yml
version: '3.8' # Compose 파일 형식의 버전입니다. 최신 버전을 사용하는 것이 좋습니다.
services:
# 'webapp' 서비스 정의
webapp:
build: . # 현재 디렉토리의 Dockerfile을 사용하여 이미지를 빌드합니다.
ports:
- "3000:3000" # 호스트의 3000번 포트를 컨테이너의 3000번 포트에 연결합니다.
volumes:
- .:/app # 현재 디렉토리를 컨테이너의 /app 디렉토리에 마운트합니다. (개발 시 코드 변경 반영용)
depends_on:
- redis # 'webapp' 서비스는 'redis' 서비스가 먼저 시작되어야 합니다.
environment: # 환경 변수 설정
REDIS_HOST: redis
NODE_ENV: development
command: npm start # 컨테이너 시작 시 실행될 명령어
# 'redis' 서비스 정의
redis:
image: "redis:alpine" # Docker Hub에서 'redis:alpine' 이미지를 가져와 사용합니다.
ports:
- "6379:6379" # 호스트의 6379번 포트를 컨테이너의 6379번 포트에 연결합니다.
# volumes:
# - redis_data:/data # Redis 데이터를 영구적으로 저장할 볼륨을 설정할 수 있습니다. (주석 처리)
# networks: # (선택 사항) 커스텀 네트워크 정의
# my_network:
# driver: bridge
# volumes: # (선택 사항) 영구 볼륨 정의
# redis_data:
참고: 위 docker-compose.yml
파일에서 webapp
서비스는 현재 디렉토리에 Dockerfile
이 있다고 가정합니다. 예를 들어, Dockerfile
은 다음과 같을 수 있습니다.
# Dockerfile (현재 디렉토리에 위치)
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
이제 이 docker-compose.yml
파일을 기반으로 필수 명령어들을 하나씩 살펴보겠습니다.
⚙️ Docker Compose 필수 명령어 총정리
Docker Compose 명령어는 크게 서비스 라이프사이클 관리, 이미지 빌드 및 관리, 서비스 상호작용 및 디버깅으로 나눌 수 있습니다.
1. 서비스 라이프사이클 관리 (생성, 시작, 중지, 제거)
1.1. docker compose up
: 서비스 빌드 및 실행 🚀
가장 많이 사용되는 명령어입니다. docker-compose.yml
파일에 정의된 모든 서비스를 빌드하고 시작합니다.
-
역할: 서비스의 이미지를 빌드(또는 풀)하고, 컨테이너를 생성한 후 시작합니다. 네트워크와 볼륨도 함께 구성합니다.
-
기본 문법:
docker compose up [서비스 이름...]
-
주요 옵션:
-d
,--detach
: 백그라운드(detached) 모드로 컨테이너를 실행합니다. 터미널을 점유하지 않아 다른 작업을 할 수 있습니다. (매우 중요!)--build
: 이미지가 이미 존재하더라도 강제로 다시 빌드합니다. Dockerfile을 변경했을 때 유용합니다.--force-recreate
: 컨테이너를 강제로 다시 생성합니다. 설정 변경 시 유용합니다.--no-deps
: 의존성을 무시하고 지정된 서비스만 시작합니다.--wait
: 모든 서비스가 healthy 상태가 될 때까지 기다립니다. (Compose V2.10.0 이상)
-
예시:
- 모든 서비스를 백그라운드로 실행하고 싶을 때:
docker compose up -d
✅ 출력:
[+] Running 2/2
…Done
이제webapp
과redis
서비스가 백그라운드에서 실행됩니다. - Dockerfile을 수정하여
webapp
서비스만 다시 빌드하고 실행하고 싶을 때:docker compose up -d --build webapp
✅
webapp
서비스가 다시 빌드되고 실행됩니다.
- 모든 서비스를 백그라운드로 실행하고 싶을 때:
1.2. docker compose down
: 서비스 중지 및 제거 🛑
up
명령어로 시작된 모든 서비스를 중지하고 관련 네트워크, 볼륨 등을 제거합니다.
-
역할:
up
명령어로 생성된 컨테이너, 네트워크, 기본 볼륨(익명 볼륨)을 중지하고 제거합니다. -
기본 문법:
docker compose down [옵션]
-
주요 옵션:
-v
,--volumes
:docker-compose.yml
에 명시된 명명된 볼륨(named volumes)까지 제거합니다. 데이터 유실에 주의하세요! ⚠️--rmi all
: 서비스에서 사용된 이미지를 제거합니다.all
은 빌드된 이미지와 다운로드된 이미지를 모두 제거합니다.--remove-orphans
:docker-compose.yml
파일에 정의되지 않았지만, 현재 프로젝트에 연결된 컨테이너도 함께 제거합니다.
-
예시:
- 모든 컨테이너와 네트워크를 제거하고 싶을 때:
docker compose down
- 컨테이너, 네트워크, 그리고 Redis 데이터 볼륨까지 완전히 제거하고 싶을 때:
docker compose down -v
🚨 주의:
redis_data
와 같은 명명된 볼륨을 사용했고-v
옵션을 사용하면 Redis 데이터가 모두 삭제됩니다.
- 모든 컨테이너와 네트워크를 제거하고 싶을 때:
1.3. docker compose start
: 중지된 서비스 시작 ▶️
이전에 docker compose stop
등으로 중지된 컨테이너를 다시 시작합니다.
- 역할: 이미 생성되어 있지만 현재 중지된 컨테이너를 다시 시작합니다.
- 기본 문법:
docker compose start [서비스 이름...]
- 예시:
webapp
서비스만 다시 시작하고 싶을 때:docker compose start webapp
1.4. docker compose stop
: 실행 중인 서비스 중지 ⏸️
실행 중인 컨테이너를 중지하지만, 컨테이너 자체는 제거하지 않습니다.
- 역할: 실행 중인 서비스를 정상적으로 종료합니다. 컨테이너는 유지됩니다.
- 기본 문법:
docker compose stop [서비스 이름...]
- 예시:
- 모든 서비스를 중지하고 싶을 때:
docker compose stop
webapp
서비스만 중지하고 싶을 때:docker compose stop webapp
- 모든 서비스를 중지하고 싶을 때:
1.5. docker compose restart
: 서비스 재시작 🔄
실행 중인 서비스를 중지했다가 다시 시작합니다.
- 역할: 특정 서비스 또는 모든 서비스를 재시작합니다.
- 기본 문법:
docker compose restart [서비스 이름...]
- 예시:
webapp
서비스만 재시작하고 싶을 때:docker compose restart webapp
2. 이미지 빌드 및 관리
2.1. docker compose build
: 서비스 이미지 빌드 🔨
docker-compose.yml
파일에 build
지시어가 있는 서비스의 이미지를 명시적으로 빌드합니다.
-
역할:
docker compose up --build
와 유사하지만, 컨테이너를 시작하지 않고 이미지 빌드만 수행합니다. CI/CD 환경이나 이미지 사전 준비 시 유용합니다. -
기본 문법:
docker compose build [서비스 이름...]
-
주요 옵션:
--no-cache
: 빌드 시 캐시를 사용하지 않습니다.--pull
: 빌드 전에 항상 기본 이미지를 다시 다운로드합니다.
-
예시:
webapp
서비스의 이미지만 다시 빌드하고 싶을 때:docker compose build webapp
2.2. docker compose pull
: 서비스 이미지 다운로드 ⬇️
image
지시어가 있는 서비스의 이미지를 Docker Hub와 같은 레지스트리에서 미리 다운로드합니다.
- 역할:
docker-compose.yml
에 정의된 서비스에서 사용할 이미지를 미리 다운로드하여up
명령 시 시간을 절약할 수 있습니다. - 기본 문법:
docker compose pull [서비스 이름...]
- 예시:
redis
이미지를 미리 다운로드하고 싶을 때:docker compose pull redis
3. 서비스 상호작용 및 디버깅
3.1. docker compose ps
: 서비스 상태 확인 ✅
현재 Compose 프로젝트의 서비스 상태를 확인합니다.
- 역할: 실행 중이거나 중지된 컨테이너의 목록, 포트 바인딩, 상태 등을 보여줍니다.
- 기본 문법:
docker compose ps [옵션]
- 예시:
- 현재 실행 중인 모든 Compose 서비스의 상태를 확인하고 싶을 때:
docker compose ps
✅ 출력:
Name Command State Ports ------------------------------------------------------------- app-redis-1 redis-server Up 0.0.0.0:6379->6379/tcp app-webapp-1 npm start Up 0.0.0.0:3000->3000/tcp
- 현재 실행 중인 모든 Compose 서비스의 상태를 확인하고 싶을 때:
3.2. docker compose logs
: 서비스 로그 확인 📜
실행 중인 서비스의 로그를 실시간으로 확인하거나 과거 로그를 조회합니다.
-
역할: 컨테이너에서 발생하는 표준 출력(stdout)과 표준 에러(stderr) 로그를 보여줍니다.
-
기본 문법:
docker compose logs [옵션] [서비스 이름...]
-
주요 옵션:
-f
,--follow
: 실시간으로 새로운 로그를 계속 출력합니다. (Ctrl+C로 종료)--tail N
: 마지막 N줄의 로그만 출력합니다.-t
,--timestamps
: 각 로그 라인에 타임스탬프를 추가합니다.
-
예시:
- 모든 서비스의 실시간 로그를 보고 싶을 때:
docker compose logs -f
webapp
서비스의 마지막 50줄 로그를 확인하고 싶을 때:docker compose logs --tail 50 webapp
- 모든 서비스의 실시간 로그를 보고 싶을 때:
3.3. docker compose exec
: 컨테이너 내부 명령어 실행 🏃♂️
실행 중인 컨테이너 내부에서 명령어를 실행합니다. 디버깅이나 쉘 접근 시 매우 유용합니다.
-
역할: 특정 서비스의 실행 중인 컨테이너 내부로 들어가 명령어를 실행합니다.
-
기본 문법:
docker compose exec [옵션] <서비스 이름> <명령어> [인자...]
-
주요 옵션:
-it
: 상호작용(interactive) 모드와 TTY 할당을 사용하여 쉘에 접속할 때 필수적입니다.
-
예시:
webapp
컨테이너 내부에 Bash 쉘로 접속하고 싶을 때:docker compose exec webapp bash # 이제 컨테이너 내부에서 명령어를 실행할 수 있습니다. # 예: ls -al, npm install # exit 입력 시 컨테이너에서 나옵니다.
redis
컨테이너 내부에서redis-cli
를 사용하여 Redis 서버 상태를 확인하고 싶을 때:docker compose exec redis redis-cli ping # PONG
3.4. docker compose run
: 일회성 컨테이너 실행 💨
특정 서비스의 새로운 컨테이너를 생성하여 일회성 명령어를 실행합니다.
-
역할:
docker compose up
으로 시작된 서비스와 독립적으로,docker-compose.yml
정의에 따라 새로운 컨테이너를 생성하고 명령을 실행한 뒤 종료합니다. 마이그레이션, 테스트, 데이터베이스 백업 등에 사용됩니다. -
기본 문법:
docker compose run [옵션] <서비스 이름> <명령어> [인자...]
-
주요 옵션:
--rm
: 명령 종료 시 컨테이너를 자동으로 제거합니다. (일회성 작업에 필수)-it
: 상호작용 모드.- `–publish
: `: 포트 포워딩.
-
exec
vsrun
차이점:exec
: 기존에 실행 중인 컨테이너 내부에서 명령을 실행.run
: 새로운 임시 컨테이너를 생성하여 명령을 실행하고,--rm
옵션을 주면 종료 후 바로 제거.
-
예시:
webapp
서비스의 환경을 사용하여 데이터베이스 마이그레이션 스크립트를 실행하고 싶을 때:docker compose run --rm webapp npm run migrate
redis
컨테이너에 접속하여 일회성으로redis-cli
를 실행하고 싶을 때:docker compose run --rm redis redis-cli keys "*"
4. 유틸리티 및 고급 명령어
4.1. docker compose config
: 설정 유효성 검사 및 보기 📝
docker-compose.yml
파일의 구문을 확인하고, 최종적으로 해석된 구성을 출력합니다.
-
역할:
docker-compose.yml
파일의 문법적 오류를 확인하고, 환경 변수 등이 적용된 최종 Compose 구성을 YAML 형식으로 보여줍니다. -
기본 문법:
docker compose config [옵션]
-
주요 옵션:
-q
,--quiet
: 경고 메시지만 출력하고, 성공 시에는 아무것도 출력하지 않습니다.--services
: 서비스 이름 목록만 출력합니다.--volumes
: 볼륨 이름 목록만 출력합니다.
-
예시:
docker-compose.yml
파일이 올바른지 확인하고 싶을 때:docker compose config
✅ 오류가 없으면 해석된 설정이 출력됩니다.
4.2. docker compose scale
: 서비스 스케일링 📈
특정 서비스의 컨테이너 개수를 조절합니다.
- 역할: 서비스의 컨테이너 인스턴스 수를 동적으로 조절합니다. 로드 밸런서와 함께 사용하면 효과적입니다. (주의: 이 명령어는 Docker Swarm 또는 Kubernetes 없이 단독으로 사용 시 로드 밸런싱 기능을 제공하지 않습니다.)
- 기본 문법:
docker compose scale <서비스 이름>=<개수>
- 예시:
webapp
서비스 컨테이너를 3개로 늘리고 싶을 때:docker compose scale webapp=3
✅
app-webapp-1
,app-webapp-2
,app-webapp-3
와 같이 여러 인스턴스가 실행됩니다.
4.3. docker compose rm
: 중지된 서비스 컨테이너 제거 🗑️
중지된 컨테이너만 제거합니다.
-
역할:
docker compose down
과 달리, 실행 중인 컨테이너는 건드리지 않고, 중지된 컨테이너만 선택적으로 제거합니다. -
기본 문법:
docker compose rm [서비스 이름...]
-
주요 옵션:
-f
,--force
: 확인 메시지 없이 강제로 제거합니다.
-
예시:
- 중지된 모든 컨테이너를 제거하고 싶을 때:
docker compose rm
- 중지된 모든 컨테이너를 제거하고 싶을 때:
4.4. docker compose version
: Docker Compose 버전 확인 ℹ️
현재 사용 중인 Docker Compose의 버전을 확인합니다.
- 역할: Docker Compose CLI의 버전을 확인합니다.
- 기본 문법:
docker compose version
- 예시:
docker compose version
✅ 출력:
Docker Compose version v2.23.3
(또는 유사한 버전)
🌟 실전 꿀팁 & 주의사항
docker-compose
vsdocker compose
:- 이 글에서는
docker compose
(하이픈이 없는) 명령어를 사용했습니다. 이는 Docker CLI에 통합된 Compose V2 플러그인의 명령어 방식입니다. - 과거에는
docker-compose
(하이픈이 있는)라는 별도의 실행 파일 방식이었습니다. - 최신 버전의 Docker를 사용한다면
docker compose
를 사용하는 것이 권장됩니다. 기능적으로는 거의 동일하지만,docker compose
가 더 현대적이고 향후 개발의 중심입니다.
- 이 글에서는
.env
파일 활용: 민감한 정보(비밀번호, API 키)나 환경에 따라 달라지는 값들은.env
파일에 정의하여docker-compose.yml
에서 참조할 수 있습니다.# .env 파일 REDIS_PASSWORD=my_secret_password APP_PORT=3000
# docker-compose.yml services: webapp: environment: REDIS_PASSWORD: ${REDIS_PASSWORD} # .env 파일의 변수 참조 ports: - "${APP_PORT}:${APP_PORT}"
- 여러 개의 Compose 파일 사용: 복잡한 프로젝트나 개발/운영 환경을 분리하고 싶을 때
-f
옵션으로 여러 개의docker-compose.yml
파일을 조합할 수 있습니다.docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
.dockerignore
파일:Dockerfile
빌드 시 불필요한 파일이나 디렉토리가 컨텍스트에 포함되지 않도록.dockerignore
파일을 사용하세요.node_modules
,.git
,.env
등을 제외하면 빌드 속도 향상 및 이미지 크기 감소에 도움이 됩니다.- Ctrl+C의 동작:
docker compose up
(detached 모드 없이) 실행 중Ctrl+C
를 누르면 컨테이너가 정상적으로 종료됩니다. 백그라운드로 실행된 서비스는docker compose stop
이나docker compose down
을 사용해야 합니다.
맺음말 ✨
지금까지 Docker Compose의 핵심 명령어들을 자세히 살펴보았습니다. docker compose up
으로 시작하여 docker compose down
으로 마무리하는 기본적인 라이프사이클부터, exec
, logs
와 같은 디버깅 도구, 그리고 scale
이나 config
같은 고급 기능까지, Docker Compose는 여러분의 컨테이너 기반 애플리케이션 개발 및 배포를 훨씬 더 쉽고 효율적으로 만들어 줄 것입니다.
이 글에서 배운 명령어들을 바탕으로 직접 docker-compose.yml
파일을 작성하고, 다양한 프로젝트에 적용해보세요. 손에 익숙해질수록 Docker Compose의 진정한 가치를 느끼실 수 있을 겁니다.
더 나아가 Kubernetes나 Docker Swarm과 같은 컨테이너 오케스트레이션 도구도 학습해본다면, 대규모 서비스 환경에서의 컨테이너 관리에 대한 이해를 더욱 높일 수 있을 거예요!
궁금한 점이 있다면 언제든지 댓글로 남겨주세요! 행복한 컨테이너 라이프 되세요! 🐳💖