목차

Docker Compose

  • kubernetes와 같이 오케스트레이션 및 컨테이너화된 애플리케이션 관리에 널리 사용되는 도구이다.
  • 다중 컨테이너 Docker 애플리케이션을 정의하고 실행하기 위한 도구이며 YAML 파일을 사용하여 애플리케이션 서비스를 수행한다.
  • CLI를 이용하여 모든 서비스 라이프 사이클을 관리한다.
  • YAML 코드를 통하여 여러개의 docker run 및 네트워크 볼륨을 생성 할 수 있다.
    • compose로 실행된 컨테이너들은 독립된 네트워크로 컨테이너 간 통신이 가능하다.
  1. Dockerfile 작성 — 배포하고자 하는 애플리케이션 환경 정의 (선택)
  2. docker-compose.yaml을 통해 하나 이상의 컨테이너 서비스를 실행할 수 있도록 서비스 정의
  3. docker compose up 명령으로 YAML에 정의된 서비스를 시작하고 실행한다.
  • 서로 다른 OS 환경이라도 동일한 환경 구성이 가능하다. (이식성)
  • 동일한 환경 사용으로 개발환경 이슈 발생시 팀간 소통이 쉽다.
  • 복잡한 환경도 YAML 코드로 스크립트화 할 수 있어 휴먼에러 감소 및 자동화가 가능하다.
  • docker compose CLI를 이용하여 쉽게 “멀티 컨테이너 애플리케이션"을 관리 할 수 있다.
  • 동시에 다수의 컨테이너 서비스를 수행하는 경우(MSA) 자원 활용률이 순간 높아질 수 있다.
  • docker container에 관한 기술 이해도가 필요하여 진입 장벽이 높다.
  • YAML? Yet Another Markup Language or YAML ain’t markup language (Text file)
  • 사람이 쉽게 읽을 수 있는 데이터 직렬화 언어(위 → 아래)로 구성파일 작성에 주로 사용된다.
  • 쉽고 이해할 수 있도록 설계되어 프로그래밍 언어로 사용되거나, 클라우드 자동환경 배포 도구(IaC 환경 구성)로 많이 사용된다 (AWS CloudFormation, RedHat Ansible 등)
항목YAMLJSON
정식명칭YAML ain’t markup languageJavaScript Object Notation
주석사용 가능사용 불가
한글/유니코드그대로 사용 가능멀티바이트 문자는 인코딩 수행
주 용도환경 구성 등의 설정 파일API 작성 시 사용

YAML 예시

version: '3.9'
services:
  mydb:
    image: mariadb:10.4.6

JSON 예시

{
    "version": "3.9",
    "services": {
        "mydb": {
            "image": "mariadb:10.4.6"
        }
    }
}
  • 중괄호, 대괄호, 닫기 태그 또는 따옴표와 같은 통상적인 형식 기호는 없다.
  • Python 스타일의 들여쓰기를 사용해 구조를 결정하고 중첩을 표기한다.
  • 이식성을 위해 들여쓰기는 tab 문자를 허용하지 않고, 공백 문자를 규칙성 있게 사용한다.
  • YAML 코드는 key, value 중심으로 작성되고, 숫자형·문자형·Boolean형을 지원한다.
    • #: 해당 라인 주석 처리
    • ---: 문서의 시작 (선택)
    • ...: 문서의 끝 (선택)

docker-compose.yaml 파일은 해당 프로젝트 최상위 디렉토리에 작성하며, 하위 프로그램의 설정과 연관성을 코드화 한다.

version: '3.9'
services:
  서비스명1:
    # 애플리케이션 설정값 정의 1
  서비스명2:
    # 애플리케이션 설정값 정의 2
networks:
  # 네트워크 설정, 미지정시 자동생성
volumes:
  # 볼륨 설정 (선택)
  • docker-compose.yaml 코드의 첫 줄은 version을 명시한다 (순서 무관)
  • version 명령은 docker engine release와 연관되어 있는 Compose file format이다.
  • 현재 Docker 엔진에 맞지 않는 버전을 사용하면 오류가 발생한다.
  • version과 동일 레벨로 작성되며 다중 컨테이너 실행을 목적으로 하기 때문에 복수형으로 작성한다.
  • 하위에는 실행될 컨테이너 서비스를 작성한다.

build — docker compose 실행시 빌드될 Dockerfile 명시

my-app:
  build:
    context: ./my-app   # Dockerfile 위치 (동일 경로면 생략 가능)
    dockerfile: Dockerfile
옵션설명docker run 대응 옵션
container_name생략시 자동 부여 → “디렉토리명_서비스명_n”--name
ports서비스 내부 포트와 외부 호스트 포트를 바인드. 외부 노출 포트 지정-p
expose서비스 포트만 노출 → 링크로 연결된 컨테이너간 통신만 필요한 경우-
networks최상위 레벨의 networks에 정의된 네트워크 이름을 작성--net / --network
volumes서비스 내부 디렉토리와 호스트 디렉토리를 연결하여 데이터 지속성 설정-v / --volume
environment서비스 내부 환경 변수 설정. 변수가 많은 경우 env_file: ./envfile.env로 분리-e
command서비스 구동 이후 실행할 명령어run 마지막 명령어
restart서비스 재시작 옵션 지정--restart
depends_on서비스간의 종속성. 먼저 실행해야 하는 서비스를 지정하여 순서 지정-

scale / deploy.replicas — 서비스 복제 컨테이너 수 지정

# v2 (deprecated)
services:
  my-el:
    image: elasticsearch:latest
    scale: 3
    # WARN: `scale` is deprecated. Use `deploy.replicas`

# v3
services:
  my-el:
    image: elasticsearch:latest
    deploy:
      replicas: 3
      mode: replicated

다중 컨테이너들이 사용할 최상위 네트워크 키들을 정의하고 이하 하위 서비스 단위로 네트워크를 선택 할 수 있다.

  • driver: 서비스의 컨테이너가 브리지 네트워크가 아닌 다른 네트워크를 사용하도록 설정
  • ipam: IPAM(IP Address Manager) — subnet, ip, gateway 범위 설정
  • external: 기존의 네트워크를 사용하도록 설정
# 미리 생성한 네트워크 사용
version: '3.9'
services:
  # ...
networks:
  default:
    external:
      name: ext-ap

# 구체적 사용자 정의 네트워크
networks:
  moon-net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.3.0.0/24
          ip_range: 172.3.0.0/24
          gateway: 172.3.0.1

데이터의 지속성을 유지하기 위해 최상위 레벨에 볼륨을 정의하고 서비스 레벨에서 볼륨명과 서비스 내부의 디렉토리를 바인드 한다. docker volume ls 명령과 docker volume inspect 볼륨명으로 확인 가능하다.

version: '3.9'
services:
  mydb:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
networks:
volumes:
  db_data: {}  # {} 생략 가능 또는 볼륨 지정

컨테이너 서비스의 상태를 체크하는 명령

version: '3.9'
services:
  # ...
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost"]
    interval: 1m00s   # 컨테이너 시작 후 30초부터 1분마다
    timeout: 10s      # 웹서비스가 10초 이내에 기본페이지를 응답해야 함
    retries: 3        # 실패시 3회 재시도
    start_period: 30s
networks:
volumes:
version: '3.9'
services:
  mysql:
    image: mysql:latest
    networks:
      - mysql
    container_name: mysql
    restart: always
    ports:
      - "3307:3306"
    environment:
      MYSQL_ROOT_PASSWORD: Mysql!
      MYSQL_USER: crimson
      MYSQL_PASSWORD: Mysql!
      TZ: Asia/Seoul
    volumes:
      - /data/docker_volumes/mysql/data:/var/lib/mysql
      - /data/docker_volumes/mysql/config:/etc/mysql/conf.d
      - /data/docker_volumes/mysql/init:/docker-entrypoint-initdb.d
networks:
  mysql:
    name: mysql
    driver: bridge