Docker Compose
Docker Compose를 왜 사용하는가?
도커 컴포즈가 없다면 우리는 여러 컨테이너들에 대한 다양한 설정들을 유지하기 위해 매우 긴 docker run
명령어와 docker build
명령어를 각 이미지 혹은 컨테이너마다 관리해야 할 것이다. 하나의 명령어에는 볼륨, 네트워크, 실행 모드, 컨테이너명, 환경 변수 등등 각종 옵션을 제공하기 위해 계속해서 태그들이 붙어 매우 길어져있는 상태일 것이다. 큰 규모의 서비스에서는 수많은 컨테이너를 사용할 것인데 이렇게 긴 명령어를 관리하는 것은 매우 복잡할 것이다.
이러한 문제를 해결하기 위해 사용되는 것이 Docker Compose라는 오케스트레이션 명령 집합이다.
Docker Compose란 무엇인가?
도커 컴포즈는 단일 혹은 다수의 docker build
와 docker run
명령을 단 하나의 구성 파일로 대체할 수 있는 도구이다.
이를 통해 모든 서비스, 모든 컨테이너를 즉시 시작하고 필요한 모든 이미지를 빌드하는 오케스트레이션 명령 집합(set)이다. 뿐만 아니라, 하나의 명령을 사용하여 모든 것을 중지하고 모든 것을 중단할 수도 있다. 당연한 말이지만, docker run
과 docker build
를 대체하기 위한 것이므로 해당 명령어에서 사용할 수 있는 다양한 옵션들은 docker-compose 파일에서도 제공한다.
도커 컴포즈 개념에 대해 학습 시 주의할 점은,
- 도커 컴포즈가 커스텀 이미지를 위한 Dockerfile을 대체하지는 않는다는 것
- 도커 컴포즈가 이미지나 컨테이너를 대체하지는 않는다는 것
- 도커 컴포즈는 서로 다른 다수의 호스트에서 다중 컨테이너를 관리하는 데는 적합하지 않다는 것
- 도커 컴포즈는 하나의 동일한 호스트에서 다중 컨테이너를 관리하는데 용이하다
도커 컴포즈는 단일 혹은 다수의 build와 run 명령을 단 하나의 구성 파일로 대체하는 도구로, 이미지 빌드 및 컨테이너 상태 관리 등에만 관심이 있다.
docker-compose.yml 구성
version: "3.8"
services:
mongodb:
image: 'mongo' // 사용할 도커 이미지(로컬이나 도커 허브에서 가져옴)
volumes:
- data:/data/db
environment:
- MONGO_INITDB_ROOT_USERNAME: max
- MONGO_INITDB_ROOT_PASSWORD: secret
# env_file: // 직접 환경변수를 넘기지 않고, env 파일을 통해 넘길 경우 사용 (--env-file 옵션)
# - ./.env
# networks:
# - goals-net
backend:
build: ./backend // 빌드 시 사용할 Dockerfile이 있는 폴더의 위치를 명시한다.
# build: // 동일한 동작을 수행하지만 더 긴 형태 (복잡한 설정을 위해 사용)
# context: ./backend
# dockerfile: Dockerfile // Dockerfile의 이름이 기본형이 아닐 때 사용한다.
# args: // 인자를 전달할 수 있다
# soem-arg: 1
ports:
- '80:80'
volumes:
- logs:/app/logs // Named 볼륨
- ./bakcend:/app // 도커 컴포즈에서는 절대 경로를 사용할 필요 없이 상대경로를 이용해도 된다!
- /app/node_modules // 익명 볼륨
environment:
- MONGODB_USERNAME: mac
- MONGODB_PASSWORD: secret
depends_on: // 컨테이너(서비스) 의존성 추가
- mongodb
frontend:
build: ./frontend
ports:
- '3000:3000'
volumes:
- ./frontend/src:/app/src
stdin_open: true // 인터렉티브 모드 활성화 (-it 중 i 옵션)
tty: true // 터미널 연결 (-it 중 t 옵션)
depends_on:
- backend
volumes: // 이 하위에 services에서 사용된 Named Volume들을 나열해야 한다 (익명 볼륨과 바운드 마운트는 X)
- data: // 단순히 인식을 위한 부분이므로 키만 존재하고 값은 없다
- logs:
- version은 사용할 docker compose의 버전을 의미한다.
- services 하위에는 mongodb, backend, frontend를 명시해주었는데 이를 통해 실행될 컨테이너의 도커에 의해 기억되는 컨테이너명을 정의할 수 있다.
- 이는 network에서 도메인 대신 컨테이너명을 입력했던 부분에서 사용된다고 생각하면 된다. 즉, 코드에서 사용할 수 있는 이름이다.
- 실제 우리가 확인하는 컨테이너명은 다르다. 이를 변경하는 방법에 대해서는 아래에서 다룬다.
- mongodb 관련 설정은 다음의 커맨드를 대체한다
docker run --name mongodb -e MONGO_INITDB_ROOT_USERNAME=max -e MONGO_INITDB_ROOT_PASSWORD=secret -v data:/data/db --rm -d --network goals-net mongo
- docker-compose를 사용하면
-d
태그와--rm
태그가 자동으로 설정된다. 즉, Detached 모드가 기본으로 실행되며 서비스 중단 시 자동으로 서비스가 제거된다. - networks 키를 추가하여 네트워크를 추가할 수 있지만, 도커 컴포즈는 해당 컴포즈 파일에 특정된 모든 서비스에 대해 새 네트워크 환경을 자동으로 생성하고 모든 서비스를 즉시 그 네트워크에 추가하기 때문에 따로 추가해줄 필요는 없다!
- backend 관련 설정은 다음의 커맨드를 대체한다
docker run --name goals-backend -e MONGODB_USERNAME=max -e MONGODB_PASSWORD=secret -v logs:/app/logs -v /Users/maruhxn/docker-complete/backend:/app -v /app/node_modules --rm -d --newtork goals-net -p 80:80 goals-node
- build 키는 우리가 수동으로 커스텀 이미지를 빌드하는 수고를 덜어준다.
- volumes 설정 시 바인드 마운트를 사용할 때, 절대 경로가 아닌 상대 경로를 입력할 수 있다는 장점이 있다!
- depends_on 키는 도커 컴포즈에만 있는 옵션으로, 여러 서비스를 만들고 시작할 때 의존성을 명시해줄 수 있다. 의존성이 생기면 해당 컨테이너가 실행된 후에야 자신도 실행된다.
- frontend 관련 설정은 다음의 커맨드를 대체한다
docker run --name goals-frontend -v /Users/maruhxn/docker-complete/frontend/src:/app/src --rrm -d -p 3000:3000 -it goals-react
- 인터렉티브 모드가 필요하므로
stdin_open
과tty
키에 모두true
값을 주자
Docker Compose Up & Down
docker-compose up
- docker-compose.yml에 명시된 서비스들을 시작한다.
-d
태그를 붙여서 Detached 모드로 실행할 수 있다.--build
옵션을 통해 이미지 리빌드를 강제할 수 있다. 이를 사용하지 않으면 기존에 생성된 이미지를 재사용할 것이다.- 명시된 이미지를 빌드만 하고 싶은 경우,
docker-compose build
명령어를 사용하자
- 명시된 이미지를 빌드만 하고 싶은 경우,
docker-compose down
- 모든 컨테이너가 삭제되고, 생성된 디폴트 네트워크와 모든 것이 종료된다.
- 볼륨은 삭제되지 않는다. 볼륨도 삭제하려면
-v
태그를 추가하자! (사용할 일은 거의 없음)
우리는 이제 복잡한 수많은 이미지 빌드 및 컨테이너 실행 명령어를 관리하기 위해 수고를 할 필요가 없다. docker-compose.yml 파일에 이러한 설정들을 모두 명시하고, docker-compose up
과 docker-compose down
이라는 2개의 명령어만 사용하면 된다!
컨테이너 이름 이해하기
docker ps를 통해 docker-compose로 실행한 컨테이너들의 이름을 확인해보면, services 하위에서 명시한 mongodb, backend, frontend라는 이름의 컨테이너명이 아닌, 다른 이름을 사용 중일 것이다. 도커 컴포즈에서 명시한 이름들은 기술적으로 단지 서비스의 이름일 뿐이며, 컨테이너 이름이 아니다. 이러한 이름은 컨테이너 이름의 일부분으로 선택된다.
실제 컨테이너 이름은 다음과 같은 형식을 갖는다
"[프로젝트 폴더 이름]_[서비스 이름]_[자동 증가되는 숫자]"
이러한 실제 컨테이너 이름을 변경하기 위해서는 container_name
이라는 키-값을 통해 설정할 수 있다
'DevOps' 카테고리의 다른 글
[Kubernetes] Kubernetes 객체의 생성 및 관리 (2) | 2024.10.21 |
---|---|
[Kubernetes] 쿠버네티스 기본 개념 (0) | 2024.10.20 |
[Docker] 네트워킹: (교차) 컨테이너 통신 (1) | 2024.10.15 |
[Docker] 볼륨과 인수 및 환경 변수 (1) | 2024.10.15 |
[Docker] 이미지와 컨테이너 (3) | 2024.10.14 |