Docker Compose
목차
- kubernetes와 같이 오케스트레이션 및 컨테이너화된 애플리케이션 관리에 널리 사용되는 도구이다.
- 다중 컨테이너 Docker 애플리케이션을 정의하고 실행하기 위한 도구이며 YAML 파일을 사용하여 애플리케이션 서비스를 수행한다.
- CLI를 이용하여 모든 서비스 라이프 사이클을 관리한다.
- YAML 코드를 통하여 여러개의 docker run 및 네트워크 볼륨을 생성 할 수 있다.
- compose로 실행된 컨테이너들은 독립된 네트워크로 컨테이너 간 통신이 가능하다.
Docker Compose 3단계 프로세스
- Dockerfile 작성 — 배포하고자 하는 애플리케이션 환경 정의 (선택)
docker-compose.yaml을 통해 하나 이상의 컨테이너 서비스를 실행할 수 있도록 서비스 정의docker compose up명령으로 YAML에 정의된 서비스를 시작하고 실행한다.
장점
- 서로 다른 OS 환경이라도 동일한 환경 구성이 가능하다. (이식성)
- 동일한 환경 사용으로 개발환경 이슈 발생시 팀간 소통이 쉽다.
- 복잡한 환경도 YAML 코드로 스크립트화 할 수 있어 휴먼에러 감소 및 자동화가 가능하다.
- docker compose CLI를 이용하여 쉽게 “멀티 컨테이너 애플리케이션"을 관리 할 수 있다.
단점
- 동시에 다수의 컨테이너 서비스를 수행하는 경우(MSA) 자원 활용률이 순간 높아질 수 있다.
- docker container에 관한 기술 이해도가 필요하여 진입 장벽이 높다.
YAML
- YAML? Yet Another Markup Language or YAML ain’t markup language (Text file)
- 사람이 쉽게 읽을 수 있는 데이터 직렬화 언어(위 → 아래)로 구성파일 작성에 주로 사용된다.
- 쉽고 이해할 수 있도록 설계되어 프로그래밍 언어로 사용되거나, 클라우드 자동환경 배포 도구(IaC 환경 구성)로 많이 사용된다 (AWS CloudFormation, RedHat Ansible 등)
코드 문법적 특징 — YAML vs JSON 비교
| 항목 | YAML | JSON |
|---|---|---|
| 정식명칭 | YAML ain’t markup language | JavaScript Object Notation |
| 주석 | 사용 가능 | 사용 불가 |
| 한글/유니코드 | 그대로 사용 가능 | 멀티바이트 문자는 인코딩 수행 |
| 주 용도 | 환경 구성 등의 설정 파일 | API 작성 시 사용 |
YAML 예시
version: '3.9'
services:
mydb:
image: mariadb:10.4.6JSON 예시
{
"version": "3.9",
"services": {
"mydb": {
"image": "mariadb:10.4.6"
}
}
}- 중괄호, 대괄호, 닫기 태그 또는 따옴표와 같은 통상적인 형식 기호는 없다.
- Python 스타일의 들여쓰기를 사용해 구조를 결정하고 중첩을 표기한다.
- 이식성을 위해 들여쓰기는 tab 문자를 허용하지 않고, 공백 문자를 규칙성 있게 사용한다.
- YAML 코드는 key, value 중심으로 작성되고, 숫자형·문자형·Boolean형을 지원한다.
#: 해당 라인 주석 처리---: 문서의 시작 (선택)...: 문서의 끝 (선택)
Docker YAML 코드 작성
docker-compose.yaml 파일은 해당 프로젝트 최상위 디렉토리에 작성하며, 하위 프로그램의 설정과 연관성을 코드화 한다.
version: '3.9'
services:
서비스명1:
# 애플리케이션 설정값 정의 1
서비스명2:
# 애플리케이션 설정값 정의 2
networks:
# 네트워크 설정, 미지정시 자동생성
volumes:
# 볼륨 설정 (선택)version
docker-compose.yaml코드의 첫 줄은 version을 명시한다 (순서 무관)- version 명령은 docker engine release와 연관되어 있는 Compose file format이다.
- 현재 Docker 엔진에 맞지 않는 버전을 사용하면 오류가 발생한다.
services
- 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: replicatednetworks
다중 컨테이너들이 사용할 최상위 네트워크 키들을 정의하고 이하 하위 서비스 단위로 네트워크를 선택 할 수 있다.
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.1volumes
데이터의 지속성을 유지하기 위해 최상위 레벨에 볼륨을 정의하고 서비스 레벨에서 볼륨명과 서비스 내부의 디렉토리를 바인드 한다.
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: {} # {} 생략 가능 또는 볼륨 지정healthcheck
컨테이너 서비스의 상태를 체크하는 명령
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