Published on

docker compose 에 대해서

Authors
  • avatar
    Name
    길재훈
    Twitter

Docker compose 에 대해서 알아본다.

Docker 를 컨테이너화 하다보면, 여러개의 Container 를 다루어야 할 일이 생긴다.

예를들면 backend, frontend, mariadb 같은 경우 말이다. 그때마다, DockerFile 을 각 Diractory 마다 지정하고, 각자
Docker build 하는건 조금 아닌듯 하다.

역시나 이러한 불편함을 없애기 위해 여러 Container 를 한번에 다룰수 있는 Docker compose 가 존재한다.

Docker compose 는 여러개의 최상의 문이 존재한다.

  • version:
    Docker-compose 의 버젼이다.
    버전에 따라, 형식의 변화가 있을 수 있으니 명시하는것이 좋다고 한다.

  • services:
    Dokcer Container 를 Build 하기 위해 명시해주는 부분이다.
    Docker-compose 는 컨테이너 생성구문을 service 개념의 단위로 작성한다.

  • volumes:
    Dockervolumn 들을 정의한다.

  • configs:
    DockerService 에서 사용될 ConfigFile 을 정의한다.

  • secrets:
    노출되서는 안되는 민감한 데이터에 대한 구성 데이터를 정의한다.
    SSH, TLS Auth key, DB Auth data 등등.. 컨테이너가 중지되면
    함께 제거된다.
    만약, secrets 정보가 필요하다면, Docker secret create 를 통해 생성가능하다.

  • networks:
    Docker container 생성시 network 설정이 가능한데, 이러한 network
    를 명시하여 작성하는 부분이다.

다음은, Docker Docs 에서 제공하는 file 내용이다.


services:
  frontend:
    image: awesome/webapp
    ports:
      - "443:8043"
    networks:
      - front-tier
      - back-tier
    configs:
      - httpd-config
    secrets:
      - server-certificate

  backend:
    image: awesome/database
    volumes:
      - db-data:/etc/data
    networks:
      - back-tier

volumes:
  db-data:
    driver: flocker
    driver_opts:
      size: "10GiB"

configs:
  httpd-config:
    external: true

secrets:
  server-certificate:
    external: true

networks:
  # The presence of these objects is sufficient to define them
  front-tier: {}
  back-tier: {}

docker compose up 의 명령을 실행하면, 먼저 현재 WorkDir 에서 docker-compose-yml 파일을 찾는다.

docker compose up;

이렇게 실행하면 --attach 모드로 시작되므로, -d 를 붙이면,
--detach 모드로 실행된다.

docker compose up -d;

만약 중지하고 싶다면, stop 옵션을 사용한다.

docker compose stop;

docker compose 로 실행한 컨테이너를 중지하고 삭제까지 하고 싶다면, down 옵션을 사용한다.

docker compose down;

다시 재시작 하고 싶다면, start 를 사용한다.

docker compose start;

또한 실행중인 Compose list 를 볼고 싶다면 ls 를 사용하면 된다.

docker compose ls;

컨테이너를 보고 싶다면 ps 를 사용한다.

docker compose ps;

이 외에도 정말 많은 commend options 들이 많다. 이를 살펴보려면 docker compose CLI 를 보도록 하자.

Docker 는 기본값으로 bridge 라는 drive 로 가상네트워크 환경을 만들어 서로가 통신할 수 있도록 만든다.

이러한 가상네트워크는 docker network create [OPTIONS] NETWORK 을 통해 생성이 가능하며, -d (--dirive) 를 통해 원하는 network drive 선택도 가능하다.

network dirve 관련해서는 아직 지식이 많이 부족하여 각 방식의 차이는 이해하지 못하고 있다.

여러개의 분산된 containerDocker engine 으로 부터 virtual IP 를 할당받고, 같은 Docker network 를 통해 서로 통신하게 된다.

또한 Container 가 교체되어 IP 주소가 변경된다 하더라도 Docker 자체에서 DNS를 이용해 서비스 디스커버리 기능을 제공하여 문제 없이 작동된다.

이를 확인하기 위해 다음의 compose file 이 존재한다고 가정해보자

version: "3"
services:
  mariadbversion: "3"
services:
  mariadb:
    image: "mariadb"
    restart: always
    volumes:
      - data:/var/lib/mysql
    env_file:
      - ./env/mariadb.env
    ports:
      - 3306
  backend:
    build:
      context: .
      dockerfile: ./dockerfiles/backend.Dockerfile
    container_name: backend
    ports:
      - 8080:8080
    volumes:
      - ./backend:/app
  frontend:
    build:
      context: .
      dockerfile: ./dockerfiles/front.Dockerfile
    container_name: frontend
    ports:
      - 3000:3000
    volumes:
      - ./frontend:/app
volumes:
  data:
:
    image: "mariadb"
    # container_name: db
    restart: always
    volumes:
      - data:/var/lib/mysql
    env_file:
      - ./env/mariadb.env
    ports:
      - 3306
  backend:
    build:
      context: .
      dockerfile: ./dockerfiles/backend.Dockerfile
    container_name: backend
    ports:
      - 8080:8080
    volumes:
      - ./backend:/app
  frontend:
    build:
      context: .
      dockerfile: ./dockerfiles/front.Dockerfile
    container_name: frontend
    ports:
      - 3000:3000
    volumes:
      - ./frontend:/app
volumes:
  data:

그리고 docker compose up -d 를 실행시켜, 각 container 를 실행시켰다.
이렇게 실행시킨다음, docker -it frontend shfrontend 에 들어간후 nslookup 을 실행시킨다.

이에 대한 결과는 다음과 같다.

> nslookup frontend

Server:         127.0.0.11
Address:        127.0.0.11:53

Non-authoritative answer:

Non-authoritative answer:
Name:   frontend
Address: 172.19.0.3


> nslookup backend
Server:         127.0.0.11
Address:        127.0.0.11:53

Non-authoritative answer:

Non-authoritative answer:
Name:   backend
Address: 172.19.0.2

> nslookup mariadb
Server:         127.0.0.11
Address:        127.0.0.11:53

Non-authoritative answer:

Non-authoritative answer:
Name:   mariadb
Address: 172.19.0.4

각 할당된 AddressIP 와 함께, DNS 이름으로 service 이름이 할당되어서 접근되는것을 볼 수 있다.

만약 db 구성을 2 개로 만들어보면 다음처럼 작동된다.

> docker compose up -d --scale mariadb=2
> nslookup mariadb
Server:         127.0.0.11
Address:        127.0.0.11:53

Non-authoritative answer:

Non-authoritative answer:
Name:   mariadb
Address: 172.19.0.5
Name:   mariadb
Address: 172.19.0.4

이건 시험용으로, 만든것으로 실상 mariadb 에는 포트번호를 붙혀줘서
backend 에서 접근해야 한다.

이건 예시일뿐이므로, 단순히 scale 을 통해 여러개의 mariadb 를 생성한것 뿐이다.

이때 제공되는 것을 보면 2개의 db 가 만들어진것을 볼 수 있다. AddressIP 별로 다르다.

하지만, DNS 조회시, 이 2개의 컨테이너가 전부 포함되는것을 볼 수 있다. 이것을 이용하면, 컨테이너에 트래픽을 고르게 분산되도록 만드는 로드벨런싱을 구현할 수 있다.

굉장히 흥미롭다.

실상 사용하는것 자체는 어렵지는 않다. 해당 내용에 맞추어 짜 들어가면 된다.

volumes 부분은, service 에 들어간 volume listnamed volume 이라면 volumes 부분에 명시해주어야 한다.

만약, 이미 docker volume create VOLUMENAME 을 사용해 해당하는 volume 이 이미 존재한다면, external flag 를 사용하여, 명시하면 해당 volume 을 사용하는것으로 알고 있다.

이는 networks 부분도 마찬가지이다.

사용하는 부분에서 약간 헷갈린 부분이 secrets 부분이다. Docs 의 예시를 보면 secretsserver-certificate 로 명시되어 있고, externalture 이다.

이는 secrets 에서 사용되는 server-certificate 가 이미 생성되어 있으므로, 생성된 secrets 를 사용하겠다는 말이다.

사실, .env 파일에서 값을 가져와서 configFile 로 설정하면 되는거 아닌가? 싶은 마음이 들기도 하지만, .env 보다 더 안전하게 보호할수 있는것같다.

이유는 값 자체를 아예 암호화시켜 버린다. 다음을 보자.

> printf "my super secret password" | docker secret create my_secret -
onakdyv307se2tl7nl20anokv

이렇게 하면 printf 의 내용을 암호화해서 my_secret 에 들어간다.

> docker secret ls

ID                          NAME                CREATED             UPDATED
onakdyv307se2tl7nl20anokv   my_secret           6 seconds ago       6 seconds ago

리스트를 확인해보면 제대로 생성된것을 볼 수 있다. 이뿐만 아니라 file 을 저장할 수도 있다.

> docker secret create my_secret ./secret.json
dg426haahpi5ezmkkj5kyl3sn

> docker secret ls

ID                          NAME                CREATED             UPDATED
dg426haahpi5ezmkkj5kyl3sn   my_secret           7 seconds ago       7 seconds ago

이렇게 생성된, secretserver-certificate 사용한다는 것이다. 사용되는 부분은 Docs 의 예시중 frontend 쪽에 나와 있는것을 확인할 수 있다.

이부분을 제대로 활용하는 방법은 Docker Swarm에서 시크릿(Secret)으로 패스워드 등 보안 정보 다루기 에서 더 살펴볼 필요가 있을 듯 싶다.

여기서 MYSQL 을 사용해 Secret 을 사용한 예시가 나오는데, 유용해 보인다.