공부/docker

도커 교과서 ch07 (도커 컴포즈)

KidAnt 2023. 12. 22. 17:41

복잡한 애플리케이션 구조를 정의하여 생성할때 Dockerfile 대신 docker compose를 이용하는게 좋다.
> 수동으로 일일이 프로세스를 지정하면 애플리케이션 오류가 일어날 확률이 높음

docker compose(도커 컴포즈)파일: 애플리케이션의 '원하는 상태' 즉 컴포넌트가 실행 중일 때 어떤 상태여야 하는지를 기술하는 파일이자 docker container run 명령으로 컨테이너를 실행할 때 지정하는 모든 옵션을 한데 모아놓은 단순한 형식으미 파일이다.

도커 컴포즈 파일 작성 후 > 도커 컴포즈 도구를 사용 > 어플리케이션 실행 > 도커 컴포즈가 필요한 도커 객체(컨테이너, 네트워크, 볼륨 등) 필요한 모든 도커 객체를 만들도록 도커 API에 명령

도커 컴포즈는 JSON으로 변환하기 쉬운 YAML문법으로 기술된다.(YAML는 들여쓰기를 통해 구조를 정의하기 때문에 들여쓰기가 중요하다.)

#to-do 애플리케이션을 실행하는 docker compose 파일
user@DESKTOP-KU8L7UV:~/080258/ch07/exercises/todo-list$ cat docker-compose.yml

version: '3.7'

services:

  todo-web:
    image: diamol/ch06-todo-list
    ports:
      - "8020:80"
    networks:
      - app-net

networks:
  app-net:
    external:
      name: nat

# version - 이 파일에 사용된 도커 컴포즈 파일 형식의 버전을 가르친다.
#(각 업데이트에 따라 버전지정이 필요하다)
# services - 애플리케이션을 구성하는 모든 컴포넌트를 열거하는 부분이다.
#(도커 컴포즈에서는 서비스 개념을 단위로 삼는 데 하나의 서비스를 같은 이미지로 
#여러 컨테이너에서 실행할 수 있기 때문이다.)
# network - 서비스 컨테이너가 연결될 모든 도커 네트워크를 열거하는 부분

 



todo web > diamol/ch06-todo-list 이미지로 부터 단일 컨테이너로 실행
> 호스트의 80보트로 자신의 8002 포트를 공개
> app-net이라는 이름의 도커 네트워크에 연결 된다. 
> docker container run -p 8020:80 --name todo-web --network nat diamol/ch06-todo-list 명령을 한 것과 같은 상태가 된다.

  • 서비스(services)아래로는 속성이 기술된다. (내용 자체는 docker container run 명령의 옵션과 그 지정값과 비슷하다)
    • image: 실행할 이미지를 지정하는 필드
    • ports: 공개할 포트에 대한 정보
    • networks: 컨테이너가 접속할 도커 네트워크를 정의하는 필드
    • 서비스의 이름은 컨테이너의 이름이자 도커 네트워크 상에서 다른 컨테이너들이 해당 컨테이너를 식별하기 위한 DNS 네임으로도 쓰인다
    • 서비스가 구성될 네트워크의 이름은 app-nat지만 network항목을 보면 이 네트워크는 nat라는 외부네트워크로 연결 된다. 즉 external 필드의 의미는 nat 네트워크가 이미 존재하므로 새로 생성하지 말라는 의미이다.

 

도커 컴포즈를 사용할려면 명령행에서 'docker-compose'명령을 실행하면 된다.

도커와 도커 컴포즈의 사용법은 다르며 따로 숙지해야 한다.
> 애플리케이션을 시작하려면 up을 사용해야한다. 그러면 도커 컴포즈가 컴포즈 파일을 체크하고 애플리케이션을 실행하기 위해 필요한 요소를 준비한다

docker-compose 명령 실행
> 현 작업 디렉토리에서 docker-compose.yml파일 검색
> 발견하면 애플리케이션 정의를 읽는다

#실습1 (도커 컴포즈  실행)

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/todo-list# docker network create nat
b00571839f24623846db038b00b9dcac51c65e92bff7021817dc8ae3382b5b2d
# 도커 네트워크인 'nat'를 생성

cd ./ch07/exercises/todo-list
#컴포즈 파일로 이동

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/todo-list# docker-compose up
Creating todo-list_todo-web_1 ... done
# 해당 명령어로 실행되고 실행시 현재 있는 리소스와 애플리케이션을 구성하는 리소스를 비교해 필요한 요소를 생성
Attaching to todo-list_todo-web_1
todo-web_1  | warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
todo-web_1  |       Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed.
todo-web_1  | warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
#어플리 케이션을 구성하는 단일 컨테이너가 실행 되면서 시동로그가 나온다.
(생략)

 

시행된 화면
훨씬 안정적으로 어플리케이션을 실행 가능

도커 컴포즈는 애플리케이션의 모든 실행 옵션이 기술되기 때문에 정보에 따른 문서화가 따로 필요가 없다.
> 간접적으로 문서화 가능

여러 서비스로 구성된 애플리케이션이라면 도커 컴포즈가 필요하다.

----------------------------------------------------------------------------------------------------------------------

#ch04의 컨테이너를 컴포즈화 시킨 파일
root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# cat 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: natroot
#accesslog는 공개하는 포트나 docker container run 명령에서 사용할 법한 설정값도 없이 이미지 이름만 적여있다.
#image-gllery는 이미지 이름과 함께 8010포트를 공개하며 
#depends_on 항목을 추가해 해당 서비스는 다른 두 항목에 의존한다는 사실도 기술했으며 
#해당 의존성을 만족하기 위해 컴포즈는 image-gallery 서비스를 실행하기 전에 
#나열된 두개의 서비스를 먼저 실행하려 시도할 것이다.



해당 서비스를 아키텍처로 그려내면 이런모양이다.

#실습2 (다중 컨테이너 도커 컴포즈)

cd /ch07/exercises/image-of-the-day/
#실습 파일로 이동

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker-compose up --detach
Pulling accesslog (diamol/ch04-access-log:)...
...(중략)
Status: Downloaded newer image for diamol/ch04-image-gallery:latest
Creating image-of-the-day_accesslog_1 ... done
Creating image-of-the-day_iotd_1      ... done
Creating image-of-the-day_image-gallery_1 ... done
#의존관계 때문에 image-gallery는 iotd와 accesslog이후에 실행된다.
#--detach: 분리 모드로 실행하는 옵션으로 컨테이너를 백그라운드에서 실행한다.





정상 작동 확인

API 서비스는 상태가 없으므로 컨테이너를 늘리는 방법으로 스케일 아웃할 수 있다.
> 웹 컨테이너가 API 데이터를 요청하면 도커가 여러개의 API 컨테이너에 이 요청을 고르게 분배해준다.

#실습 3 (API 분배)
root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker-compose up -d --scale iotd=3
image-of-the-day_accesslog_1 is up-to-date
Creating image-of-the-day_iotd_2 ... done
Creating image-of-the-day_iotd_3 ... done
image-of-the-day_image-gallery_1 is up-to-date
#intd 서비스를 스케일링해 컨테이너가 두개가 추가된다.

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker-compose logs --tail=1 iotd
Attaching to image-of-the-day_iotd_3, image-of-the-day_iotd_2, image-of-the-day_iotd_1
iotd_1           | 2023-12-21 06:40:38.570  INFO 1 --- [p-nio-80-exec-1] iotd.ImageController                     : Fetched new APOD image from NASA
iotd_2           | 2023-12-21 06:51:00.163  INFO 1 --- [p-nio-80-exec-2] iotd.ImageController                     : Fetched new APOD image from NASA
iotd_3           | 2023-12-21 06:50:51.974  INFO 1 --- [           main] iotd.Application                         : Started Application in 2.599 seconds (JVM running for 2.902)
#각 iotd의 최근 인트리를 알려준다. 
#iotd 3은 요청을 처리한 적이 없으며 1 2는 요청 받아 데이터를 전달한 흔적이 있다.



도커 컴포즈가 사용자를 대신해 컨테이너를 관리하지만 컴포즈를 통한 수동 관리 또한 가능하다. 또한 도커나 도커 컴포즈나 같은 도커 API를 사용하므로 도커 컴포즈로 만들었어도 똑같이 도커 명령어를 적용이 가능하다.

#실습4 (도커 컴포즈 컨테이너에 도커 명령어 사용하기)

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker-compose stop
Stopping image-of-the-day_iotd_3          ... done
Stopping image-of-the-day_iotd_2          ... done
Stopping image-of-the-day_image-gallery_1 ... done
Stopping image-of-the-day_accesslog_1     ... done
Stopping image-of-the-day_iotd_1          ... done
#중지된 컨테이너는 리소스를 점유하지 않지만 파일시스템은 유지된다.

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker-compose start
Starting accesslog     ... done
Starting iotd          ... done
Starting image-gallery ... done
#컨테이너 재시작

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker container ls
CONTAINER ID   IMAGE                          COMMAND                  CREATED          STATUS          PORTS                                     NAMES
6a3b39a3cfac   diamol/ch04-image-of-the-day   "java -jar /app/iotd…"   20 minutes ago   Up 39 seconds   0.0.0.0:32771->80/tcp, :::32771->80/tcp   image-of-the-day_iotd_3
fa251a8fdbf7   diamol/ch04-image-of-the-day   "java -jar /app/iotd…"   20 minutes ago   Up 39 seconds   0.0.0.0:32772->80/tcp, :::32772->80/tcp   image-of-the-day_iotd_2
922b29fa28d5   diamol/ch04-image-gallery      "/web/server"            33 minutes ago   Up 38 seconds   0.0.0.0:8010->80/tcp, :::8010->80/tcp     image-of-the-day_image-gallery_1
f1e60f09dff1   diamol/ch04-access-log         "docker-entrypoint.s…"   33 minutes ago   Up 40 seconds   80/tcp                                    image-of-the-day_accesslog_1
6ea2ab73abbc   diamol/ch04-image-of-the-day   "java -jar /app/iotd…"   33 minutes ago   Up 39 seconds   0.0.0.0:32773->80/tcp, :::32773->80/tcp   image-of-the-day_iotd_1
#컨테이너 목록을 확인하면 30분 전에 생성됬고 방금 재시작 된것이 출력된다.



도커 컴포즈는 어디까지나 사용자측에서 동작하는 도구이며 명령을 실행하면 도커 API로 지시를 보낸다.
> 도커 엔진자체는 컨테이너를 시행할 뿐 동작 여부까지는 알지 못하며 이를 아는 것은 YAML로 이루어진 컴포즈 파일을 이해한 도커 컴포즈 뿐이다.(컴포즈 파일이 필요한 이유)

컴포즈 파일을 수정하거나 도커 명령으로 애플리케이션을 직접 수정
> 애플리케이션이 컴포즈 파일에 기술된 구조와 불일치 상태 가능
> 해당 상태에서 도커 컴포즈로 재관리시 비정상적인 동작을 보일 수 있다.

#실습5 (컴포즈 제거 및 재생성)
root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker-compose down
Stopping image-of-the-day_iotd_3          ... done
Stopping image-of-the-day_iotd_2          ... done
Stopping image-of-the-day_image-gallery_1 ... done
Stopping image-of-the-day_accesslog_1     ... done
Stopping image-of-the-day_iotd_1          ... done
Removing image-of-the-day_iotd_3          ... done
Removing image-of-the-day_iotd_2          ... done
Removing image-of-the-day_image-gallery_1 ... done
Removing image-of-the-day_accesslog_1     ... done
Removing image-of-the-day_iotd_1          ... done
Network nat is external, skipping
#반드시 컴포즈 파일이 있는 폴더에서 진행할 것
#애플리케이션, 컨테이너 종료 및 리소스 삭제
#네트워크가 external로 지정되어 있으므로 삭제되지 않고 고대로 남아있는다.

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker-compose up -d
Creating image-of-the-day_iotd_1      ... done
Creating image-of-the-day_accesslog_1 ... done
Creating image-of-the-day_image-gallery_1 ... done
#컴포즈 파일에 정의된 리소스를 다시 생성 및 애플리케이션 재시작

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker container ls
CONTAINER ID   IMAGE                          COMMAND                  CREATED          STATUS          PORTS                                     NAMES
98d85393bb98   diamol/ch04-image-gallery      "/web/server"            20 seconds ago   Up 19 seconds   0.0.0.0:8010->80/tcp, :::8010->80/tcp     image-of-the-day_image-gallery_1
b7c47d82df72   diamol/ch04-image-of-the-day   "java -jar /app/iotd…"   21 seconds ago   Up 20 seconds   0.0.0.0:32774->80/tcp, :::32774->80/tcp   image-of-the-day_iotd_1
37bacc0cfeb5   diamol/ch04-access-log         "docker-entrypoint.s…"   21 seconds ago   Up 20 seconds   80/tcp                                    image-of-the-day_accesslog_1
#컴포즈 파일이 수정되지 않았으므로 그대로 진행되어 iotd 서비스는 하나이다.


external 플래그가 붙지 않으면 볼륨이든 네트워크든 컴포즈 파일에 포함되었다면 제거 대상이다.

도커엔진은 자체적으로  애플리케이션 끼리 어떤 관계인지 알수 없다 그로므로 컴포즈 파일을 통해 리소스를 관리해야 애플리케이션이 성립된다


--------------------------------------------------------------------------------------------------------------------------

컨테이너는 별도의 네트워크 공간을 가진 가상환경
> 도커엔진으로 부터 가상 IP를 부여받으며 모두 같은 도커 네트워크로 연결된다(LINK 제외)
>애플리케이션 생애주기 동안 컨테이너가 교체되면 IP도 변경된다.
> IP주소가 변경돼도 문제없도록 도커에서 DNS를 이용해 서비스 디스커버리 기능을 제공

DNS
> IP to 도메인

도커에도 DNS 서비스가 내장되어 있다.
> 컨테이너에서 실행중인 애플리케이션도 다른 구성 요소에 접근하기 위해 DNS 서비스를 사용한다.

#실습1 (도커 네트워크 DNS 조회)

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker-compose up -d --scale iotd=3
Starting image-of-the-day_iotd_1      ... done
Creating image-of-the-day_iotd_2 ... done
Creating image-of-the-day_iotd_3 ... done
Starting image-of-the-day_accesslog_1 ... done
Starting image-of-the-day_image-gallery_1 ... done
#오탈 주의
#애플리케이션 실행 (iotd 3개)

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker container exec -it image-of-the-day_image-gallery_1 sh
#컨테이너의 쉘 실행

/web # nslookup accesslog
nslookup: can't resolve '(null)': Name does not resolve

Name:      accesslog
Address 1: 172.18.0.3 image-of-the-day_accesslog_1.nat
#accesslog의 dns 도메인 조회

/web # exit
#나가기

#DNS 조회를 통해 도커 네트워크가 사설 네트워크인 172번대를 사용하는 것을 알 수 있다.(172.16~172.31 B클래스)


도커 네트워크에 연결된 모든 컨테이너는 네트워크의 범위에 맞는 대역대를 DHCP처럼 부여받으며 이것으로 상호간 통신이 가능하다.
> 컨테이너가 교체되 IP가 변하더라도 DNS조회를 통해를 통해 항상 새로 만들어진 컨테이너로 접속 가능하다.

#실습2 (도커 네트워크 DNS 재조회)

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker container rm -f image-of-the-day_accesslog_1
image-of-the-day_accesslog_1
#accesslog 삭제

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker-compose up -d --scale iotd=3
image-of-the-day_iotd_1 is up-to-date
image-of-the-day_iotd_2 is up-to-date
image-of-the-day_iotd_3 is up-to-date
Creating image-of-the-day_accesslog_1 ... done
image-of-the-day_image-gallery_1 is up-to-date
#애플리케이션의 상태가 컴포즈 파일의 상태가 다른걸 감지하고 컴포즈가 새로운 accesslog 컨테이너를 만들어 대응한다.

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/image-of-the-day# docker container exec -it image-of-the-day_image-gallery_1 sh
#image-gallery 내부를 쉘로 접근

/web # nslookup accesslog
nslookup: can't resolve '(null)': Name does not resolve

Name:      accesslog
Address 1: 172.18.0.3 image-of-the-day_accesslog_1.nat
#새로운 컨테이너는 기존의 accesslog 컨테이너의 ip를 그대로 유지한다.(기존 컨테이너가 삭제되었기 때문에 ip 재사용이 가능해진 것)

/web # nslookup iotd
nslookup: can't resolve '(null)': Name does not resolve

Name:      iotd
Address 1: 172.18.0.5 image-of-the-day_iotd_2.nat
Address 2: 172.18.0.2 image-of-the-day_iotd_1.nat
Address 3: 172.18.0.6 image-of-the-day_iotd_3.nat
#iotd 서비스는 세개의 컨테이너로 작동하기 때문에 ip 주소도 3개가 조회된다.(이때문에 트래픽 분산도 가능해진다)

/web # exit


-------------------------------------------------------------------------------------------------------------

소규모라면 SQLite를 사용해도 상관없으나 대규모 라면 원격 컨테이너에소서 동작하는 PostgreSQL DB를 추천한다.

PostgreSQL: 강력한 기능을 갖춘 오픈 소스 관계형 DBMS, 폭넓은 용도로 사용, 도커에서도 호환이 좋으며 분산형 애플리케이션에도 적합하다.

#postgresql을 사용하는 to-do 애플리케이션 서비스
root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/todo-list-postgres# cat docker-compose.yml
version: "3.7"

services:
  todo-db:
    image: diamol/postgres:11.5
    ports:
      - "5433:5432"
    networks:
      - app-net

  todo-web:
    image: diamol/ch06-todo-list
    ports:
      - "8030:80"
    environment:
      - Database:Provider=Postgres
    depends_on:
      - todo-db
    networks:
      - app-net
    secrets:
      - source: postgres-connection
        target: /app/config/secrets.json

networks:
  app-net:

secrets:
  postgres-connection:
    file: ./config/secrets.json

# environment:컨테이너 안에서 사용될 환경변수 값이 정의됨
#(환경변수 Database:Provider값이 Postgres로 설정된다.)
# secrets: 실행 시 컨테이너 내부 파일에 기록될 비밀값을 정의한다.
#(애플리케이션이 실행되면 컨테이너의 /app/config/secrets.json 파일이 생기고, 해당 파일에는 postgresql-connection 이라는 비및갑의 값이 기록된다.)
# secrets(비밀값): 주로 클러스터 환경에서 쿠버네티스나 도커 스윔같은 컨테이너 플랫폼을 통해 제공된다, 민감한 정보로 구성된 설정값을 전달하는데 적합하다. 
#(postgres-connection값을 secrets.json 파일에서 읽어오라는 의미)

 

실습1 (PostgreSQL로 to-do 애플리케이션 해보기)

cd ~/ch07/exercises/todo-list-postgres
#해당 파일로 이동

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/todo-list-postgres# docker-compose up -d
Creating network "todo-list-postgres_app-net" with the default driver
Pulling todo-db (diamol/postgres:11.5)...
11.5: Pulling from diamol/postgres
....(중략)
Status: Downloaded newer image for diamol/postgres:11.5
Creating todo-list-postgres_todo-db_1 ...
Creating todo-list-postgres_todo-db_1 ... done
Creating todo-list-postgres_todo-web_1 ... done
#컴포즈로 애플리케이션이 실행되고 postgresql DB와 to-do 웹이 시작된다.

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/exercises/todo-list-postgres# docker-compose ps
            Name                           Command              State                    Ports
----------------------------------------------------------------------------------------------------------------
todo-list-postgres_todo-db_1    docker-entrypoint.sh postgres   Up      0.0.0.0:5433->5432/tcp,:::5433->5432/tcp
todo-list-postgres_todo-web_1   dotnet ToDoList.dll             Up      0.0.0.0:8030->80/tcp,:::8030->80/tcp

#컴포즈에 포함된 컨테이너 목록을 보여준다
#to-do 웹은 겉으로는 같아 보이나 db가 postgresql에 저장된다는 점이 다르다


-------------------------------------------------------------------------------------------------------------

  • 컴포즈를 사용하기전에 목적은 무엇이고 어떤 기능과 어떤 제한사항이 있는지를 이해해야 한다 
    • 컴포즈를 사용하면 애플리케이션을 정의하고 이 정의를 도커 엔진을 실행중인 단일 컴퓨터에 적용할 수 있다.
    •  도커 리소스를 파악하고 컴포즈의 리소스와 비교하여 필요한 리소스만 도커 api를 통해 요청해서 수정하거나 생성한다.
  • docker-compose up을 서서 실행하기만 하면 컴포즈 파일대로 실행할 수 있지만 단지 그뿐이다
    • 도커 스윔이나 쿠버네티스 같은 컨테이너 플랫폼이 아니기 때문에 지속적으로 상태를 유지시키는 것에 한계가 있다.
    • 일부 컨테이너가 오류를 일으켜도 up을 써서 다시 실행하지 않는 이상 되돌릴 수 없다.

  • 개발환경~운영환경 이행까지 도커 컴포즈 사용하기 적합한 시기
    • 개발자가 애플리케이션을 실행하고 앤드 투 앤드 테스트를 수행할 때
    • 지속적 통합 프로세스중 빌드 및 자동화된 테스트에 컴포즈를 사용해 애플리케이션을 실행할 때
    • 단일 서버에서 컴포즈를 실행해 테스트를 진행하면 테스트 환경을 최소한으로 가능하다
    • 운영 환경에서는 컴포즈 보다는 도커 스윔이나 쿠버네티스가 적합하다. 그러나 애플리케이션 정의에는 컴포즈 파일 포맷을 사용한다.

  • 그렇다고 운영환경에 완전히 부적합하지는 않다 
    • 애플리케이션의 일관적인 요소들의 조합을 만들 수 있다.

----------------------------------------------------------------------------------------------------------------------

연습문제

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/lab# cat docker-compose-dev.yml
version: "3.7"

services:
  todo-web:
    image: diamol/ch06-todo-list
    ports:
      - "8020:80"
    environment:
      - Database:Provider=Sqlite
    networks:
      - app-net

networks:
  app-net:
    external:
      name: nat
#environment로 환경변수 Database:Provider값이 Sqlite로 설정

root@DESKTOP-KU8L7UV:/home/user/080258/ch07/lab# cat docker-compose-test.yml
version: "3.7"

services:
  todo-db:
    image: diamol/postgres:11.5
    restart: unless-stopped
    environment:
      - PGDATA=/var/lib/postgresql/data
    volumes:
      - type: bind
        source: /data/postgres
        target: /var/lib/postgresql/data
    networks:
      - app-net

  todo-web:
    image: diamol/ch06-todo-list
    restart: unless-stopped
    ports:
      - "8050:80"
    environment:
      - Database:Provider=Postgres
    depends_on:
      - todo-db
    secrets:
      - source: postgres-connection
        target: /app/config/secrets.json

secrets:
  postgres-connection:
    file: postgres-connection.json

networks:
  app-net:
    external:
      name: nat
#restart: 컨테이너 종료 시 플랫폼이 적용하는 정책을 설정
# no: 디폴트 정책, 어떤 상황에서도 다시시작 X
# always: 컨테이너가 제거될 때까지 항상 컨테이너를 다시 시작
# on-failure: 종료 중 오류가 발생하는 경우 다시 시작
#unless-stopped: 종료형식과 상관없이 항상 다시시작 하지만 오류 발생이나 컨테이너가 제거될 중지

docker-compose -f docker-compose-dev.yml up -d

mkdir -p /data/postgres

docker-compose -f docker-compose-test.yml up -d

도커 볼륨 초기화 명령
docker volume rm -f $(docker volume ls)

실습환경 초기화 명령
docker container rm -f $(docker container ls -aq)

이미지 차지 디스크 용량 회수 명령
docker image rm -f $(docker image ls -f reference='diamol/*' -q)