[Docker] Docker-Compose 작성하기
docker compose가 없으면 네트워크 통신을 하는 다중 컨테이너를 실행하기 위해 실행해야 할 과정이 복잡해진다. 매번 도커 이미지를 빌드(build)하고, 컨테이너를 실행(run)하면서 옵션을 넣어주어야 하며 따라서 CLI 명령어도 길어진다. 다음은 docker-compose 없이 Web Frontend - Backend - DB 를 구축하는 커맨드를 나열한 예시이다.
# 컨테이너가 공유할 네트워크 생성
docker network create my_network
# 1. Run MongoDB Container
docker run --name mongodb \
-e MONGO_INITDB_ROOT_USERNAME=max \
-e MONGO_INITDB_ROOT_PASSWORD=secret \
-v data:/data/db
--rm \
-d \
--network my_network \
mongo
# 2. Build Node API Image
docker build -t my_node .
# 3. RUN Node API Container
docker run --name my-backend \
-e MONGO_INITDB_ROOT_USERNAME=max \
-e MONGO_INITDB_ROOT_PASSWORD=secret \
-v logs:/app/logs \
-v /Users/app/backend:/app \
-v /app/node_modules \
--rm \
-d \
--network my-network \
-p 80:80 \
my-node
# 4. Build React SPA Image
docker build -t my-react .
# 5. RUN Node API Container
docker run --name my-frontend \
-v /Users/app/frontend/src:/app/src \
--rm \
-d \
-p 3000:3000
-it \
my-react
# 6. Stop all Containers
docker stop mongdb my-backend my-frontend
docker-compose는 이러한 다중 컨테이너 설정을 더 쉽게 관리할 수 있게 만드는 도구이다. 도커 컴포즈를 통해 설정 프로세스를 자동화하는 데 도움을 받을 수 있다. 또한 단 하나의 명령만으로도 모든 컨테이너와 각 컨테이너의 개별 구성을 지닌 전체 설정을 가져오게 한다. 컨테이너 제거 또한 마찬가지로 쉽게 할 수 있다.
Docker Compose
다수의 'docker build' 명령과 'docker run' 명령을 단 하나의 구성 파일로 만들어 오케스트레이션 커맨드(build, start, stop..)를 실행시킨다. 단일 컨테이너 애플리케이션에서도 도커 컴포즈를 사용 가능하다.
Docker Compose가 아닌 것
- 커스텀 이미지를 위한 Dockerfile을 대체하지는 않는다. 오히려, 도커 컴포즈는 도커파일과 함께 작동한다.
- 이미지나 컨테이너를 대체하지 않는다. 작업하는 것을 쉽게 만들거나 컨테이너를 더 쉽게 시작하게 만든다.
- 다수의 호스트에서 다중 컨테이너를 관리하는 데는 적합하지 않다. 하나의 호스트에서 다중 컨테이너를 관리하는 데 적합하다.
Docker Compose 파일 작성하기
도커 컴포즈 파일에서 멀티 컨테이너를 구성하는 핵심 구성 요소를 정의한다. 도커 컴포즈에서 정의해야 하는 가장 중요한 요소는 서비스(services)이다. 이 서비스는 실제로 컨테이너를 의미한다. 도커 컴포즈 파일의 확장자는 .yml 또는 .yaml 으로, 구성 옵션 간의 종속성을 표현하는 특정한 텍스트 포맷이다. 작성에 앞서 visual studio를 사용한다면, Docker extension을 설치하면 편한다.
1. version 정의
- version은 앱이나 파일의 버전이 아니다. 사용하려는 도커 컴포즈 사양의 버전이다.
- 도커 컴포즈 사양의 버전은 컴포즈 파일에서 사용할 수 있는 기능에 영향을 미친다.
- https://docs.docker.com/compose/compose-file/compose-file-v3/
2. services 작성
- 들여쓰기(indent)를 하는 것이 중요하다. yaml을 들여쓰기로 종속성을 표현하고, 이에 두 개의 공백을 사용한다.
- services에는 최소한 하나의 하위 요소(컨테이너)가 필요하다.
- image를 작성한다. image는 로컬이나 도커 허브 레포지터리에서 조회된다.
- 이미지가 저장될 수 있는 다른 저장소에 대한 전체 URL도 가능하다.
- ports를 작성한다. 개방하려는 포트에 대해 대시(-) 후 포트를 문자열 추가한다.
- volumns을 작성한다. 추가하려는 모든 볼륨에 대해 대시(-) 후 볼륨을 추가한다.
- 볼륨의 끝에 ':ro' (읽기 전용)와 같이 부가 옵션을 추가할 수 있다.
- services 내의 volumn을 작성 후 마지막에 services와 같은 최상위 수준의 volumns를 쓰고
services에서 사용 중인 명명된 볼륨을 나열해야 한다. 명명된 볼륨은 이름만 쓰고, 콜론(:)
뒤에는 따로 적어주지 않아도 된다. (도커가 명명된 볼륨을 인식하기 위해 필요한 구문)
익명 볼륨과 바인드 마인트는 적지 않는다. - volumn 이름은 '프로젝트_볼륨명' 으로 생긴다.
- services 내의 volumn을 작성 후 마지막에 services와 같은 최상위 수준의 volumns를 쓰고
- 볼륨의 끝에 ':ro' (읽기 전용)와 같이 부가 옵션을 추가할 수 있다.
- environment를 작성한다. 한 줄 띄우고, 들여쓰기를 한 후 '환경변수명: 설정값' 을 쓴다.
- yaml 에서는 'key: value' 로 값을 넣을 때는 앞 쪽에 대시(-)는 필요하지 않다.
- '환경변수명: 설정값' 대신 '- 환경변수명=설정값' 을 쓸 수도 있다.
- environment 대신 환경변수 파일을 지정하여 쓸 수도 있다.
- docker run 커맨드에서는 --env-file 을 썼다.
- docker compose에서는 'environment' 대신 'env_file: \ - 환경변수 파일 상대경로' 를 쓴다.
- ETC
- networks는 지정할 수도 있지만, 도커 컴포즈 파일 빌드 시 새 네트워크를 자동으로 생성하고 모든 서비스를 즉시 그 네트워크에 추가하기 때문에 기재를 하지 않아도 된다. 네트워크 이름은 '프로젝트 이름_default'로 생긴다.
- 기존 도커 CLI에서 --rm 옵션을 컴포즈 파일에는 넣을 필요가 없다. default로 설정되어 있다.
- default로 attach 모드로 실행된다. detach 모드로 실행시 실행 명령어에 -d 옵션을 넣는다.
- depends_on 은 도커 컴포즈에만 있는 옵션이다. 서비스간 의존성에 의해 먼저 실행되야 하는 서비스가 있을 경우 도커에게 알려주는 역할을 한다.
version: "3.8"
services:
mongodb:
image: 'mongo'
volumns:
- data:/data/db
# container_name: mongodb
environment:
MONGO_INITDB_ROOT_USERNAME: max
# - MONGO_INITDB_ROOT_USERNAME=max
MONGO_INITDB_ROOT_PASSWORD: secret
# env_file:
# - ./env/mongo.env
# networks:
# - my-network
backend:
build: ./backend
# build:
# context: ./backend
# dockefile: Dockerfile-dev
# args:
# some-arg: 1
ports:
- '80:80'
volumns:
- logs:/app/logs
- ./backend:/app
- /app/node_modules
env_file:
- ./env/backend.env
depends_on:
- mongodb
frontend:
build: ./frontend
ports:
- '3000:3000'
volumns:
- ./frontend/src:/app/src
stdin_open: true
tty: true
depends_on:
- backend
volumns:
data:
logs:
Docker Compose 실행 & 중지
docker-compose.yaml 파일이 있는 프로젝트 경로에서 다음 명령어를 실행한다.
# 서비스 실행
docker-compose up
# detach 모드로 서비스 실행
docker-compose up -d
# 이미지 리빌드를 강제로 수행
docker-compose up --build
# 서비스 중지 & 모든 컨테이너 제거 (볼륨은 삭제되지 않음)
docker-compose down
# 볼륨까지 모두 제거
docker-compose down -v
Reference
https://www.udemy.com/course/docker-kubernetes-2022/