docker compose는 쿠버네티스와 같이 컨테이너 오케스트레이션 및 컨테이너화된 애플리케이션에 사용되는 도구입니다.
지금까지 도커 CLI를 통해 실행시키는 컨테이너는 단일 컨테이너 서비스였습니다.
도커 컴포즈는 다중 컨테이너 도커 애플리케이션을 정의하고 실행하기 위한 도구이고 특이점은 yaml 파일을 사용하여 애플리케이션을 수행한다는 것입니다.-> 선언적 구성
이후에는 docker compose CLI를 통해 서비스의 라이프 사이클을 관리합니다.
Docker compose
기본적으로 도커 컴포즈는 응집력 있는 애플리케이션으로 함께 작동하는 여러 컨테이너를 실행하려는 로컬 개발 및 테스트 환경을 위해 설계된 도구입니다.
여기서 응집력있는 애플리케이션은 하나의 웹 애플리케이션을 생성하는 3-Tier 환경이라고 칩니다.
클라이언트 -> 서버 -> DB 이런 3-Tier 애플리케이션을 docker compose를 통해 함께 작동시키며 응집력 있다고 합니다.
docker compose yaml 코드는 여러 개의 docker run 실행과 유사하며 네트워크, 볼륨 등을 한 번에 생성, 실행시킬 수 있습니다.
- 기본 이미지, 노출된 포트, 환경 변수, 컨테이너 간의 종속성 등을 포함하는 컨테이너들에 대한 구성 지정
- docker compose로 실행된 컨테이너들은 독립된 네트워크로 구성되므로 컨테이너 간 통신이 쉽다.
docker compose 3단계 프로세스
- Dockerfile 작성으로 배포하고자 하는 애플리케이션 환경 정의(선택)
- docker-compose.yml (or compose.yml) 하나 이상의 컨테이너 서비스를 실행할 수 있도록 서비스 정의
- docker compose up 명령으로 YAML 코드로 정의된 서비스를 시작하고 실행한다.
장점
- 서로 다른 OS 환경이라도 동일한 환경 구성이 가능하다.(이식성)
- 동일한 환경을 사용하기 때문에 개발환경에 이슈가 발생해도 팀 간 소통이 쉽다.
- 복잡한 환경도 YAML 코드로 스크립트화 할 수 있기 때문에 자동화가 가능하다.
- docker compose CLI를 이 요 오하여 쉽게 "멀티 컨테이너 애플리케이션"을 관리할 수 있다.
단점
- 동시에 다수의 컨테이너 서비스를 수행하는 경우(MSA) 자원 활용률이 순간 높아질 수 있다.
- docker compose 사용은 충분한 docker container 기술에 대한 이해도가 필요하다.
비교 | docker compose | kubernetes |
사용 범위 | 단일 호스트(로컬)에서의 개발, 테스트 및 소규모 배포에 적합 | 클러스터로 구성된 전체 머신을 기반으로 컨테이너화 된 애플리케이션 배포에 적합 |
구조 | 단일 시스템에서 컨테이너 간의 실행, 상호 작용 및 족송성 관리 | 클러스터의 여러 노드에서 컨테이너를 오케스트레이션하고 확장, 로드밸런싱 매커니즘 제공 |
확장성 및 고가용성 | 여러 호스트 서비스 지원하지 않음, 단 docker swarm 클러스터에서는 지원 -> stack | 수요에 따른 애플리케이션 자동 확장 및 분산, 컨테이너 재시작 및 자동 장애 처리 기능 제공 |
서비스 검색 및 로드 밸런싱 | 자체 네트워크 생성. 컨테이너 연결지원 및 서비스 간 포트 노출. 자체 로드 밸런싱 없음 | DNS 기반 서비스 검색과 다중 컨테이너 간 분산 처리하는 로드밸런싱 제공 |
롤링 업데이트 및 배포 전략 | 수동적 롤링 업데이트만 지원 | 다운 타임 없이 컨테이너 업데이트 가능. Blue/ green 및 카나리아 배포 같은 배포 전략 제공 |
YAML 코드 작성 방법
version
- 일반적으로 docker-compose.yml 코드의 첫 줄은 version을 명시한다.(순서 무관)
- version 명령은 docker engine release와 연관되는 Compose file format이다.
- 현재 Docker 엔진에 맞는 버전을 사용한다.
services
- docker compose는 컨테이너 대신 service 개념을 사용하고, 상위의 version 명령과 동일 레벨로 작성되며 다중 컨테이너 서비스 실행을 목적으로 하기 때문에 복수형으로 작성한다.
- services 하위에는 실행될 컨테이너 서비스를 작성하고, 하위 레벨에 Docker 명령 실행과 유사하게 컨테이너 실행에 필요한 옵션들을 작성한다.
version: "3.8"
services:
서비스명1:
# 컨테이너에 필요한 옵션들 설정
서비스명2:
# 컨테이너에 필요한 옵션들 설정
build
docker compose 실행 시 빌드될 Dockerfile 명시
version: "3.8"
services:
서비스명1:
# 컨테이너에 필요한 옵션들 설정
build:
context: ./hello-app # Dockerfile 위치(동일 경로면 생략 가능)
dockerfile: Dockerfile # 제공하는 Dockerfile 이름
서비스명2:
# 컨테이너에 필요한 옵션들 설정
container_name
생략 시 자동으로 부여, 디렉터리명_서비스명_n
docker run --name 옵션과 동일
ports
서비스 내부 포트와 외부 호스트 포트를 지정하여 바인드. 외부 노출 포트 지정. docker run의 -p 옵션과 동일
expose
호스트 운영체제와 직접 연결하는 포트를 구성하지 않고, 서비스만 포트를 노출 링크로 연결된 컨테이너, 서비스와 서비스 간의 통신만 필요한 경우에 사용
networks
최상위 레벨의 networks에 정의된 네트워크 이름을 작성. docker run --net(--network) 옵션과 동일
volumes
서비스 내부 디렉터리와 호스트 디렉터리를 연결하여 데이터 지속성 설정. docker run -v(--volume) 옵션과 동일
environment
서비스 내부 환경 변수 설정
환경 변수가 많은 경우 파일(*. env)로 만들어 env_file 옵션에 파일명을 지정 -> env_file:./envfile.env
docker run -e 옵션과 동일
command
서비스가 구동 이후 실행할 명령어 작성.
docker run의 마지막에 작성되는 명령어
restart
서비스 재시작 옵션 지정.
docker run --restart 옵션과 동일
depends_on
서비스 간의 종속성을 의미하며 먼저 실행해야 하는 서비스를 지정하여 순서 지정.
이 옵션에 지정된 서비스가 먼저 시작됨
scale
해당 서비스의 복제 컨테이너수 지정(V2) -> (V3) deploy.replicas로 변경
여기서는 container_name을 주면 안 된다. -> 컨테이너에서 이름은 유니크해야 하기 때문에 자동생성 방법으로 해야 함
scale 명령어를 사용하고 싶으면 docker-compose --compatibility up -d
services:
jisu:
image: jisu:1.0
deploy:
replicas: 3
mode: replicated
networks
다중 컨테이너들이 사용할 최상위 네트워크 키들을 정의하고 이하 하위 서비스 단위로 이 네트워크를 선택할 수 있다.
- driver : 서비스 컨테이너가 브리지 네트워크가 아닌 다른 네트워크를 사용하도록 설정
- ipam: IPAM(IP Address Manager)를 위해 사용할 수 있는 옵션으로 subnet, ip, gateway 범위 설정
- external : 기존의 네트워크를 사용하도록 설정
volumes
데이터의 지속성을 유지하기 위해 최상위 레벨에 볼륨을 정의하고, 서비스 레벨에서 볼륨명과 서비스 내부의 디렉터리를 바인드 한다.
docker volume create와 동일하게 Docker가 관리하는 /var/lib/docker/volume에 자동으로 배치된다.
docker volume ls , docker volume inspect 볼륨명으로 확인 가능함
services:
jisu:
image: jisu:1.0
volumes:
- data:/var/lib/jisu
networks:
volumes:
jisu: {} # {} 생략 가능
docker compose를 통한 애플리케이션 배포 yml 작성법
환경은 보통의 애플리케이션처럼 이렇습니다.
프런트서버, Nginx, 스프링 부트 백엔드, MySQL 서버 1대 모두 도커 이미지를 통해 배포 방법을 소개해볼까 합니다.
docke- compose.yml
version: '3.8'
services:
mysql-db:
image: mysql:5.7-debian
container_name: mysql-db
environment:
MYSQL_ROOT_PASSWORD: pass123
MYSQL_DATABASE: jisu
MYSQL_ROOT_HOST: '%'
MYSQL_USER: user
MYSQL_PASSWORD: user
ports:
- '3306:3306'
networks:
- my-app-net
restart: always
command:
- --character-set-server=utf8
- --collation-server=utf8_general_ci
my-app-back:
build:
context: ./my-app-back # 백엔드를 빌드할 도커파일이 있는 위치
dockerfile: Dockerfile
deploy:
replicas: 3
restart: always
depends_on:
- mysql-db
ports:
- '8081-8083:8080' # 8080으로 요청이오면 8081, 8082, 8083 으로 로드밸런싱
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql-db:3306/jisu
SPRING_DATASOURCE_USERNAME: user
SPRING_DATASOURCE_PASSWORD: user
networks:
- my-app-net
my-app-front:
build:
context: ./my-app-front # 프런트를 빌드할 도커파일이 있는 위치
dockerfile: Dockerfile
deploy:
replicas: 3
restart: always
depends_on:
- my-app-back
ports:
- '3000-3002:3000'
networks:
- my-app-net
proxy-be:
image: nginx:1.21.5-alpine
container_name: proxy-server-lb
restart: always
depends_on:
- my-app-back
ports:
- '8080:80'
volumes:
- ${PWD}/proxy/nginx-be.conf:/etc/nginx/nginx.conf
networks:
- my-app-net
proxy-fe:
image: nginx:1.21.5-alpine
container_name: proxy-front-lb
restart: always
ports:
- '80:80'
volumes:
- ${PWD}/proxy/nginx-fe.conf:/etc/nginx/nginx.conf
networks:
- my-app-net
networks:
my-app-net: {}
docekr compose를 사용해 보셨다면 위의 명령어들이 어떻게 돌아가실지 알 것입니다.
하나하나 설명해 보겠습니다.
services: mysql-db
- image: mysql 이미지를 사용하겠다.
- continer_name : 도커 컨테이너의 이름
- environment: 도커 mysql의 환경 변수
- posts : docker에 포트 설정
- networks : 도커 네트워크 설정 -> 도커는 같은 네트워크를 사용한다면 컨테이너 이름으로 DNS 사용 가능
my-app-back
- 스프링 백엔드 서버입니다.
- build : 도커 파일을 가지고 빌드를 하겠다.
- context : 빌드할 도커파일의 경로를 작성해 줍니다.
- dockerfile: 빌드할 도커 파일의 이름을 작성해 줍니다.
- deploy:replicas : 띄우고자 하는 컨테이너의 개수를 적어줍니다.
- restart : 오류로 인하여 컨테이너가 다운되는 상황에서 항상 재시작하겠다.
- depends_on : 의존성을 갖겠다. -> 여기서는 mysql-db의 빌드 및 구동한 후 실행되게 합니다.
- ports : 도커 컨테이너의 내부 IP를 설정해 줍니다. -> 8081~8083:8080 은 8080 , 8080 요청이 오면 8081,8082,8083으로 포워딩해주는 포트를 설정
- environment: 환경 변수
proxy-be
nginx를 설정하고 위의 설명들과 다 같습니다.
다른 점은 볼륨을 통해 미리 정의해 놓은 conf 파일을 마운팅 해줍니다.
이렇게 도커 컴포즈의 명령어와 작성 법 배포 시 yml 작성법을 알아봤는데 기본적으로 docker network 방식으로 구동되며
단일 호스트 내에서만 지원되므로 작은 규모의 애플리케이션을 사용할 때 사용해 보면 좋을 것 같습니다.
'docker' 카테고리의 다른 글
[docker] 컨테이너 오케스트레이션 docker swarm cluster (1) | 2023.10.29 |
---|---|
[Docker] Dockerfile (4) | 2023.10.26 |
[Docker] 컨테이너 리소스 모니터링 (0) | 2023.10.24 |
[docker] Volume (3) | 2023.10.23 |
[Docker] Docker 로그인 방법 (0) | 2023.10.21 |
댓글