도커 컴포즈

mohadang·2022년 6월 16일
0

도커

목록 보기
26/26
post-thumbnail

여러 개의 컨테이너가 하나의 어플리케이션으로 동작할 때 이를 테스트하려면 각 컨테이너를 하나씩 생성해야 한다.
EX)

웹 어플리케이션을 테스트하려면 웹 서버 컨테이너와 데이터베이스 컨테이너를 생성해야 한다.
$ docker run --name mysql -d alicek106/composetest:mysql mysqld
$ docker run -d -p 80:80 --link mysql:db --name web alicek106/composetest:web apachectl -DFOREGROUND

매번 run 명령어에 옵션을 설정해 CLI로 컨테이너를 생성하기보다는 여러 개의 컨테이너를 하나의 서비스로 정의해 컨테이너 묶음으로 관리할 수 있다면 좀 더 편리할 것이다. 도커 컴포즈는 컨테이너를 이용한 서비의 개발과 CI를 위해 여러 개의 컨테이너를 하나의 프로젝트로서 다룰 수 있는 작업 환경을 제공한다.

도커 컴포즈는 여러 개의 컨테이너의 옵션과 환경을 정의한 파일을 읽어 컨테이너를 순차적으로 생성하는 방식으로 동작

도커 컴포즈의 설정 파일은 run 명령어의 옵션을 그대로 사용할 수 있으며, 각 컨테이너의 의존성, 네트워크, 볼륨 등을 함께 정의할 수 있다. 또한 스웜 모드의 서비스와 유사하게 설정 파일에 정의된 서비스의 컨테이너 수를 유동적으로 조절할 수 있으며 컨테이너의 서비스 디스커버리도 자동으로 이뤄진다.

컨테이너의 수가 많아지고 정의해야 할 옵션이 많아진다면 도커 컴포즈를 사용하는 것이 좋다.

도커 컴포즈 설치

  • 리눅스 : github 저장소에서 직접 내려받아 설치
$ sudo curl -L \
"https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
  • 윈도우, Mac: 도커 툴박스나 Docker for Windows, Docker for Mac을 설치하면 도커 엔진과 함께 도커 컴포즈도 설치

도커 컴포즈 사용

기본 사용법

  • 컨테이너의 설정이 정의된 YAML 파일을 읽어 도커 엔진을 통해 컨테이너를 생성
  • 도커 컴포즈를 사용하려면 가장 먼전 YAML 파일을 작성해야 한다.

EX)

- command line
$ docker run --name mysql -d alicek106/composetest:mysql mysqld
$ docker run -d -p 80:80 --link mysql:db --name web alicek106/composetest:web apachectl -DFOREGROUND

- YAML
version: '3.0'
services:
  web:
    image: alicek106/composetest:web
    ports:
      - "80:80"
    links:
      - mysql:db
    command: apachectl -DFOREGROUND
  mysql:
    image: alicek106/composetest:mysql
    command: mysqld

YAML 파일에서 들여쓰기할 때 탭은 토커 컴포즈가 인식하지 못하므로 2개의 공백을 사용해 하위 항목을 구분해야 한다.

  • version : YHAML 파일 포맷의 버전. 도커 컴포즈 1.8은 버전 2, 도커 컴포즈 1.9는 버전 2.1, 도커 컴포즈 1.10은 버전 3.0 사용
  • services : 생성될 컨테이너들을 묶어놓은 단위, 서비스 항목 아래에는 각 컨테이너에 적용될 생성 옵션을 지정
  • web, mysql : 생성될 서비스의 이름. 이 항목 아래에 컨테이너가 생성될 때 필요한 옵션을 지정 가능

어떠한 설정도 하지 않으면 도커 컴포즈는 현재 디렉터리의 docker-compose.yml 파일을 읽어 로컬의 도커 엔진에게 컨테이너 생성을 요청

EX) docker-compose up -d

root@red-virtual-machine:~# docker-compose up -d
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

Starting root_mysql_1 ... done
Starting root_web_1   ... done

root@red-virtual-machine:~# docker ps
CONTAINER ID   IMAGE                         COMMAND                  CREATED         STATUS         PORTS                               NAMES
4a1b113148bb   alicek106/composetest:web     "apachectl -DFOREGRO…"   5 minutes ago   Up 6 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   root_web_1
e770ecdd511d   alicek106/composetest:mysql   "mysqld"


docker compose 파일로 컨테이너 생성

EX) docker-compose ps

$ docker-compose ps
    Name              Command           State                Ports
--------------------------------------------------------------------------------
root_mysql_1   mysqld                   Up
root_web_1     apachectl -DFOREGROUND   Up      0.0.0.0:80->80/tcp,:::80->80/tcp

도커 컴포즈의 프로젝트, 서비스, 컨테이너

도커 컴포즈는 컨테이너를 프로젝트 및 서비스 단위로 구분하므로 컨테이너의 이름은 일반적으로 다음과 같은 형식으로 정해진다.

[프로젝트 이름]_[서비스 이름]_[서비스 내에서 컨테이너의 번호]

서비스 : web, mysql
컨테이너 : root_web_1, root_mysql_1

스웜 모드에서의 서비스와 마찬가지로, 하나의 서비스에는 여러 개의 컨테이너가 존재할 수 있으므로 차례대로 증가하는 컨테이너의 번호를 붙여 서비스 내의 컨테이너를 구별

EX) docker-compose scale mysql=2

$ docker-compose scale mysql=2
$ docker ps
CONTAINER ID   IMAGE                         COMMAND                  CREATED          STATUS         PORTS                               NAMES
2d78825c529d   alicek106/composetest:mysql   "mysqld"                 3 seconds ago    Up 1 second                                        root_mysql_2
4a1b113148bb   alicek106/composetest:web     "apachectl -DFOREGRO…"   10 minutes ago   Up 4 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   root_web_1
e770ecdd511d   alicek106/composetest:mysql   "mysqld"                 10 minutes ago   Up 4 minutes                                       root_mysql_1

EX) docker-compose up

$ docker-compose up -d mysql

서비스의 이름을 입력해 docker-compose.yml 파일에 명시된 특정 서비스의 컨테이너만 생성할 수 있다.

EX) docker-compose run

$ docker-compose run web /bin/bash

run 명령어로 컨테이너를 생성할 수 있다. 이때는 Interactive 셸을 사용할 수 있다.

EX) docker-compose down

root@red-virtual-machine:~# docker-compose down
Stopping root_mysql_2 ... done
Stopping root_web_1   ... done
Stopping root_mysql_1 ... done
Removing root_mysql_2 ... done
Removing root_web_1   ... done
Removing root_mysql_1 ... done
Removing network root_default

생성된 docker-compose 프로젝트는 docker-compose down 명령어로 삭제 가능

도커 컴포즈는 기본적으로 현재 디렉터리의 이름으로 된 프로젝트를 제어
예를 들어 /home/ubuntu 디렉터리에 docker-compose.yml 파일이 있고, docker-compose down 명령어를 사용하면 ubuntu라는 이름을 가진 프로젝트를 삭제
docker-compose의 -p 옵션에 프로젝트의 이름을 사용해 제어할 프로젝트의 이름을 명시 가능
$ docker compose -p myproject up -d // myproject 라는 이름으로 프로젝트 생성
$ docker compose -p myproject ps // myproject 프로젝트에 ps
$ docker compose -p myproject down // myproject 프로젝트에 down

도커 컴포즈 활용

YAML 파일 작성

도커 컴포즈를 사용하려면 컨테이너 설정을 저장해 놓은 YAML 파일이 필요
기존에 사용하던 run 명령어를 YAML 파일로 변환하는 것이 도커 컴포즈 사용버의 대부분
YAML 파일 구성

  • 버전 정의
  • 서비스 정의
  • 볼륨 정의
  • 네트워크 정의

EX) docker-compose -f

$ docker-compose -f /home/alicek106/my_compose_file.yml up -d

YAML 파일 우치 지정

1. 버전 정의

version:

'3.0'
버전 3은 도커 스웜 모드와 호환되는 버전이므로 가능하면 최신 버전의 도커 컴포즈를 사용하는 것이 좋다.

2. 서비스 정의

services:
  my_container_1:
    image: ...
  my_container_2:
    image: ...

image :

서비스의 컨테이너를 생성할 때 쓰일 이미지의 이름 설정. 만일 이미지가 도커에 존재하지 않으면 저장소에서 자동으로 내려 바등ㅁ

docker run 명령어의 --link와 같음. 다른 서비스에 서비스명만으로 접근할 수 있도록 설정 [SERVICE:ALIAS]의 형식을 사용하면 서비스에 별칭으로도 접근 가능

services:
  web:
    links:
      - db
      - db:database
      - redis

environment :

docker run 명령어의 --env, -e 옵션과 동일. 서비스의 컨테이너 내부에서 사용할 환경변수를 지정. 딕셔너리나 배열 형태로 사용 가능

services:
  web:
    environment:
      - MYSQL_ROOT_PASSWORD=mypassword
      - MYSQL_DATABASE_NAME=mydb
      
      또는
      
    environment:
      - MYSQL_ROOT_PASSWORD: mypassword
      - MYSQL_DATABASE_NAME: mydb      

command :

컨테이너가 실행될 때 수행할 명령어를 설정. docker run 명령어의 마지막에 붙는 커맨드. Dockerfile의 RUN과 같은 배열 형태로도 사용 가능

services:
  web:
    image: alicek106/composetest:web
    command: apachectl -DFOREGROUND
    
    또는
    
    image: alicek106/composetest:web
    command: [apachectl, -DFOREGROUND]

depends_on :

특정 컨테이너에 대한 의존 관계를 나타내며 이 항목에 명시된 컨테이너가 먼저 생성되고 실행. links도 depends_on과 같이 컨테이너의 생성 순서와 실행 순서를 정의하지만 depends_on은 서비스 이름으로만 접근 가능


web 컨테이너보다 mysql 컨테이너가 먼저 생성

services:
  web:
    image: alicek106/composetest:web
    depends_on
      - mysql 
  mysql:
    image: alicek106/composetest:mysql
    
특정 서비스의 컨테이너만 생성하되 의존성이 없는 컨테이너를 생성하려면 --no-deps 옵션 사용
$ docker-compose up --no-deps web

entrypoint :

links, depends_on 모두 실행 순서만 설정할 뿐 컨테이너 내부의 애플리케이션이 준비된 상태인지에 대해서는 확인하지 않는다. 데이터베이스 컨테이너와 웹 서버 컨테이너가 정해진 순서대로 실행됐더라도
데이터베이스가 초기화 중이라면 웹 서버 컨테이너가 정상적으로 동작하지 않는다.
이를 해결하는 방법으로 컨테이너에 셸 스크립트를 entrypoint로 지정하는 방버이 있다.
YAML 파일의 entrypoint에 다음과 같이 지정

services:
  web:
    ...
    entrypoint: ./sync_script.sh mysql:3306

entrypoint에 지정된 sync_script.sh는 다음과 같은 형식을 가진다.
unilt 구문의 조건 안에 다른 컨테이너의 어플리케이션이 준비됐는지 확인하는 명령어를 입력. 예를 들러 curl mysql:3306을 조건으로 넣는다면 myslq 데몬이 준비될 때까지 기다릴 것이다.
until (상태를 확인할 수 있는 명령어): do
echo "depend container is not available yet"
sleep 1
done
echo "depends_on container is ready"

port :

run 명령어의 -p와 같으며 서비스의 컨테이너를 개발할 포트를 설정
그러나 단일 호스트 환경에서 80:80과 같이 호스트의 특정 포트를 서비스의 컨테이너에 연결하면 docker-compose scle 명령어로 서비스의 컨테이너의 수를 늘릴 수 없다.

services:
  web:
    image: alicek106/composetest:web
      ports:
        - "8080"
        - "8081-8085"
        - "80:80"

build :

도커파일에서 이미지를 빌드해 서비스의 컨테이너를 생성하도록 설정

services:
  web:
    build: ./composetest
    image: alicek106/composetest:web

composetest 디렉터리에 저장된 도커파일로 이미지를 빌드해 컨테이너를 생성
새롭게 빌드될 이미지의 이름은 image 항목에 정의된 이름인 alicek106/composetest:web이 된다.

services:
  web:
    build: ./composetest
    context: ./composetest
    dockerfile: myDockerfile
    args:
      HOST_NAME: web
      HOST_CONFIG: self_config

도커파일에서 사용될 인자 값을 설정 가능
image 항목을 설정하지 않으면 이미지의 이름은 [프로젝트 이름]:[서비스 이름]이 된다.

build 항목을 YAML 파일에 정의해 프로젝트를 생성하고 난 뒤 도커파일을 변경하고 다시 프로젝트를 생성해도 이미지를 새로 빌드하지 않는다.

  • docker-compose up -d에 --build 옵션을 추가하거나 docker-compose build 명령어를 사용해 도커파일이 변경돼도 컨테이너를 생성할 때마다 빌드하도록 설정 가능
  • $ docker-compose up -d --build
  • $ docker-compose build [yml 파일에서 빌드할 서비스 이름]

extends :

다른 YAML 파일이나 현재 YAML 파일에서 서비스 속성을 상속받게 설정

EX) 설정을 상속 받은 docker-compose.yml 파일

version: '3.0'
  services:
    web:
      extends:
        file: extend_compose.yml
        service: extend_web

EX) 설정을 상속해줄 extend-compose.yml 파일

version: '3.0'
  services:
    web:
      extends_web:
        image: ubuntu:14.04
        ports:
          - "80:80"        

EX) 같은 파일에서 상속

version: '3.0'
  services:
    web:
      extends:
        service: extend_web  
    extends_web:
      image: ubuntu:14.04
      ports:
        - "80:80"        

그러나 depends_on, links, volumes_from 항목은ㅇ 각 컨테이너 사이의 의존성을 내포하고 있으므로 extends로 상속받을 수 없다

도커 컴포즈의 일부 버전에서 extends가 동작하지 않을 수 있다. 이를 해결하려면 최신 버전의 도커 컴포즈를 사용하거나 version 항목을 3.0이 아닌 2.x로 내려 사용

3. 네트워크 정의

driver :

도커 컴포즈는 생성된 컨테이너를 위해 기본적으로 브리지 타입의 네트워크를 생성
YAML 파일에서 driver 항목을 정의해 서비스의 컨테이너가 브리지 네트워크가 아닌 다른 네트워크를 사용하도록 설정 가능

version: '3.0'
services:
  myservice:
    image: nginx
    networks:
      - mynetwork
networks:
  mynetwork:
    driver: overlay
    driver_opts:
      subnet: "255.255.255.0"
      IPAddress: "10.0.0.2"

docker-compose up -d 명령어로 컨테이너를 생성할 때 mynetwork라는 overlay 타입의 네트워크도 함께 생성
myservice 서비스의 네트워크가 mynetwork 네트워크를 사용하도록 설정
단 overlay 타입의 네트워크는 스웜 모드나 주키퍼를 사용하는 환경이어야만 생성 가능

ipam :

IPAM(IP Addresss Manager)를 위해 사용할 수 있는 옵션. subnet, ip 범위 등을 설정할 수 있다. driver 항목에는 IPAM을 지원하는 드라이버의 이름을 입력

services:
  ...
networks:
  ipam:
    driver: mydriver
    config:
      subnet: 172.20.0.0/16
      ip_range: 172.20.5.0/24
      gateway: 172.20.5.1

external:

YAML 파일을 통해 프로젝트를 생성할 때마다 네트워크를 생성하는 것이 아닌, 기존의 네트워크를 사용하도록 설정
이를 설정하려면 사용하려는 외부 네트워크의 이름을 하위 항목으로 입력한 뒤 external의 값을 true로 설정
external 옵션은 준비된 네트워크를 사용하므로 driver, driver_ops, ipam 옵션과 함께 사용할 수 없다.

services:
  web:
    image: alicek106/composetest:web
    networks:
      - alicek106_network
networks:
  alicek106_network:
    external: true

서비스의 컨테이너가 기존의 alicek106_netowrk라는 이름의 네트워크를 사용하도록 설정

4. 볼륨 정의

driver:
볼흄을 생성할 때 사용될 드라이버를 설정. 어떠한 설정도 하지 않으면 local로 설정

version: '3.0'
servicees:

volumes:
  driver: flocker
    driver_opts:
      opt: "1"
      opt2: 2
드라이버를 사용하기 위한 추가 옵션은 하위 항목인 driver_opts를 통해 인자로 설정 가능
      


servicees:
  web:
    image: alicek106/composetest:web
    volumes:
      - myvolume:/var/www/html

volumes:
  myvolume:
    external: true
    
external 설정하면 볼륨을 생성할 때마다 매번 생성하지 않고 기존 볼륨을 사용하도록 설정
다음 예제에서 myvolume이라는 이름의 외부 볼륨을 web 서비스의 컨테이너에 마운트

5. YAML 파일 검증

YAML 파일을 작성할 때 오타 검사나 파일 포맷이 적절하지 등을 검사하려명 docker-compose config 명령 사용

$ docker-compose config
$ docker-compose -f (yml 파일 경로)

도커 컴포즈 네트워크

YAML 파일에 네트워크 항목을 정의하지 않으면 도커 컴포즈는 프로젝트별로 브리지 타입의 네트워크를 생성
생성된 네트워크의 이름은 [프로젝트 이름]_default로 설정. docker-compose up 명령어로 생성되고 docker-compose down 명령어로 삭제
docker-compose up 명령어뿐 아니라 docker-compose scale 명령어로 생성되는 컨테이너 전부가 이 브리지 타입의 네트워크를 사용

서비스 내의 컨테이너는 --net-alias가 서비스의 이름을 갖도록 자동으로 설정
이 네트워크에 속한 컨테이너는 서비스의 이름으로 서비스 내의 컨테이너에 접근 가능
EX)

web 서비스와 mysql 서비스가 각기 존재할 때 web 서비스의 컨테이너가 mysql이라는 호스트 이름으로 
접근하면 mysql 서비스의 컨테이너 중 하나의 IP로 변환(resolve)되며 컨테이너가 여러 개 존재할 경우 
라운드 로빈으로 연결을 분산

따라서 docker-compose scle 명령어로 컨테이너의 수를 늘려도 해당 서비스의 이름으로 서비스의 
모든 컨테이너에 접근할 수 있다.
profile
mohadang

0개의 댓글