docker 교과서 Chapter 7
docker-compose는 여러 컨테이너를 하나의 호스트에서 관리할 수 있게 도와준다. docker-cli만 가지고선 이미지를 빌드하는 방법에 대한 별도의 문서를 마련해야 했지만, docker-compose가 선언형으로 컨테이너들을 실행하는데 필요한 단계와 속성을 정의하여 편해졌다.
docker-compose.yml 파일 예제
version: '3.7'
services:
accesslog:
image: diamol/ch04-access-log
networks:
- app-net
iotd:
image: diamol/ch04-image-of-the-day
ports:
- "80"
networks:
- app-net
image-gallery:
image: diamol/ch04-image-gallery
ports:
- "8010:80"
depends_on:
- accesslog
- iotd
networks:
- app-net
networks:
app-net:
external:
name: nat
version
: docker-compose 자체의 버전을 명시한다.services
: container와 같은 개념. 위의 예제는 하나의 컨테이너만을 정의하는 예제이다.networks
: 도커 네트워크를 정의.external
을 사용하면 자동생성을 방지한다. networks # external 참조depends_on
: 컨테이너 실행 순서를 정의한다. 즉, 아래에 나열된 원소들이 먼저 실행이 된 다음에 자신의 서비스가 실행이 된다.
더 많은 옵션을 원한다면 https://docs.docker.com/reference/compose-file/services/ 에서 확인 가능하다.
docker-compose CLI cheatsheet
scale 옵션은 동일한 컨테이너를 스케일 아웃하는데 사용된다. 스케일 아웃된 컨테이너에 요청이 들어오면 도커컴포즈가 이븐하게 요청을 나눠주어 부하를 막아준다.
도커는 자체적으로 DNS 기능까지 포함하고 있는데, 컨테이너 이름 (--name
옵션)이 DNS 테이블에 포함되어 있는 것을 확인할 수 있다.
$ docker exec -it image-of-the-day-image-gallery-1 sh
/web # nslookup iotd
Name: iotd
Address 1: 172.18.0.4 image-of-the-day-iotd-3.nat
Address 2: 172.18.0.3 image-of-the-day-iotd-2.nat
Address 3: 172.18.0.5 image-of-the-day-iotd-1.nat
docker-compose의 한계
단일 서버에서의 컨테이너들을 관리하기 때문에 분산 서비스 아키텍처를 계획중이라면 도커 스웜이나 쿠버네티스와 같은 플랫폼을 사용해야 한다. 하지만 배포환경이 그렇게 크지 않거나 CI, 테스팅을 위한 간소한 환경을 구축하고자 한다면 docker-compose는 좋은 선택이다.
docker-compose의 한계, 오케스트레이션의 등장
연습문제
diamol/ch06-todo-list
를 기반으로 하는 도커 컴포즈 스크립트를 작성하시오. 이때 아래의 조건을 포함해야 한다:
- 호스트 컴퓨터가 재부팅 되거나 도커 엔진이 재시작되면 애플리케이션 컨테이너도 재시작 되어야 한다.
- 데이터베이스 컨테이너는 바인드 마운트에 파일을 저장하여 영속성을 보장하라.
- 테스트를 위해 웹 애플리케이션은 80번 포트를 주시하도록 하라.
version: "2.7"
services:
todo-db:
image: diamol/postgres:11.5
ports:
- "5433:5432"
networks:
- nat
environment:
- PGDATA=/var/lib/postgresql/data
# 바인드 마운트에 파일을 저장해 영속성 보장
volumes:
- type: bind
# source와 target이랑 계속 혼동이 와...
source: /data/postgres # ⇒ 호스트 파일시스템
target: /var/lib/postgresql/data # ⇒ 컨테이너 경로, environment.PGDATA와 동일한 값을 가져야 함.
bind:
create_host_path: true # volumes.source 경로에 디렉터리가 없으면 자동으로 생성
restart: always # 또는 unless-stopped
todo-app:
image: diamol/ch06-todo-list
ports:
- "80:80"
environment:
- Database:Provider=Postgres
depends_on:
- todo-db
networks:
- nat
secrets:
- source: postgres-connection
target: /app/config/secrets.json
restart: always # 또는 unless-stopped
networks:
nat:
driver: bridge
external: true
secrets:
postgres-connection:
file: ./config/secrets.json
usql로 postgres://postgres:postgres@localhost:5433/todo
에 접속한 뒤 테이블 SELECT를 했더니 데이터가 로컬 파일 시스템에 저장되는 것을 볼 수 있다!
2번 볼륨은 굳이 바인드 할 필요 없이 도커 볼륨을 써도 될 것 같은데