파란하늘의 지식창고
반응형

https://docs.docker.com/compose/

개요

Docker compose는 여러 개의 container를 정의하고 실행하기 위한 도구이다.
compose를 사용하면 yaml 파일을 사용해서 서비스를 구성할 수 있다.
compose는 모든 환경 (production, staging, development, test, CI workflow)에서 동작한다.

compose 사용은 기본적으로 3단계 프로세스이다.

  1. 모든 환경에서 재생산할 수 있게 Dockerfile을 정의
  2. 격리된 환경에서 함께 실행할 수 있도록 docker-compose.yml로 앱을 구성하는 서비스를 정의
  3. docker-compose up 명령으로 전체 앱을 시작

docker-compose.yml의 모양은 다음과 같다.

version: '3'
services:
  web:
    build: .
    ports:
    - "5000:5000"
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
volumes:
  logvolume01: {}

compose는 전체 lifecycle을 관리하기 위해 커맨드를 제공한다.

  • start, stop, rebuild 서비스
  • 실행 중인 서비스 상태 보기
  • 실행 중인 서비스의 로그 출력 스트리밍
  • 서비스에서 일회용 명령 실행

compose를 사용하지 않으면 각각의 container의 lifecyle에 대해 일일이 명령을 수행해야 한다.
그렇게 사용하는 것도 스크립트를 이용하거나 하는 방법으로 해결할 수 있지만 묶음으로 lifecycle을 관리해주는 compose를 사용하면 여러 개의 container를 사용하는 게 훨씬 편해진다.

특징

compose는 다음과 같은 특징을 가진다.

  • 단일 host상 여러 격리된 환경
  • container 생성 시 volume data 보존
  • 변경된 container만 다시 재생성
  • 변수와 환경 간 composition 이동

단일 host상 여러 격리된 환경

compose는 project name을 사용하여 서로 환경을 격리한다.
여러 다른 상황에서 이 프로젝트 이름을 사용할 수 있다.

  • dev host에서 프로젝트의 각 branch에 대해 안정적인 복사본을 실행하려는 경우 단일 환경의 여러 복사본을 만들 수 있다.
  • CI 서버에서 빌드가 서로 간섭하지 않도록 하려면 project name을 고유한 빌드 번호로 설정할 수 있다.
  • 공유 host 또는 dev host에서 동일한 service name을 사용할 수 있는 서로 다른 프로젝트가 서로 간섭하지 않도록 방지
    default project name은 project direct의 이름이다.
  • p 명령행 옵션이나 COMPOSE_PROJECT_NAME 환경 변수를 사용해서 사용자 정의 프로젝트 이름을 설정할 수 있다.

격리된 환경이라고 문서상 표현되어 있는데 기존에 설명한 적 있는 Docker network를 말한다.

docker-compose up 명령 실행 시 별도의 network가 생성되고 docker-compose.yml에 포함된 서비스는 모두 해당 network에 포함된다.
docker-compose down 명령 실행 시 해당 network는 자동으로 삭제된다.

container 생성 시 volume data 보존

compose는 서비스에서 사용하는 모든 volume을 보존한다.
docker-compose up이 실행될 때 이전 실행에서 container를 찾으면 volume을 이전 container에서 새 container로 복사한다.
이 프로세스에서 작성한 모든 데이터가 손실되지 않도록 한다.

변경된 container만 다시 재생성

변경되지 않은 서비스를 다시 시작할 때 compose는 기존 container를 다시 사용한다.

변수와 환경 간 composition 이동

compose 파일에서 compose가 변수를 지원한다.
이 변수를 사용하여 서로 다른 환경 또는 다른 사용자에 맞게 구성을 사용자 정의할 수 있다.

사용해보기

docker-compose 명령어의 버전은 다음과 같이 확인할 수 있다.

docker-compose -v
# 호출 결과는 아래처럼 나온다.
docker-compose version 1.29.2, build 5becea4c

spring cloud의 netflix-eureka-server, config-server, admin-server이 3개의 container를 띄우기 위해 사용해보았다.
만약 Dockerfile을 통해 image를 만든 상태라면 다음처럼 사용할 수 있다.

version: '3'

services:
  netflix-eureka-server:
    image: bluesky-cloud-netflix-eureka-server
    ports:
      - '8761:8761'
    environment:
      - SPRING_PROFILES_ACTIVE=dockerdev

  config-server:
    image: bluesky-cloud-config-server
    ports:
      - '8888:8888'
    environment:
      - SPRING_PROFILES_ACTIVE=dockerdev
    depends_on:
      - netflix-eureka-server

  admin-server:
    image: bluesky-cloud-admin-server
    ports:
      - '8889:8889'
    environment:
      - SPRING_PROFILES_ACTIVE=dockerdev
    depends_on:
      - netflix-eureka-server

해당 docker-compose.yml 파일이 있는 위치에서 다음 명령을 실행한다.

docker-compose up -d

-d는 데몬으로 실행 옵션이다.

중지하려면 다음 명령을 실행한다.

docker-compose down

down 하는 즉시 기존에 생성된 container가 삭제된다.
따로 docker rm 명령을 통해 삭제할 필요가 없다.

이렇게 실행된 docker container는 기존 docker ps를 통해 확인할 수 있지만 아래와 같이 해당 docker-compose로 생성된 container 그룹을 확인할 수 있다.

docker-compose ps

docker-compose로 실행된 container의 경우 docker-compose.yml 파일이 위치한 directory의 name을 기준으로 container name이 생성된다.

만약 다른 이름으로 project name을 변경하길 원한다면 아래처럼 -p 옵션을 사용하면 된다.

docker-compose -p blueskyProject up -d

이 경우 중지 시에도 동일 옵션으로 추가해야 중지할 수 있다.

docker-compose -p blueskyProject down

이와 같이 동일한 docker-compose.yml로 -p name을 지정하여 동시에 여러 개의 docker compose ps를 생성할 수도 있다.

만약 특정 directory 아래 docker-compose.yml이 아닌 다른 이름으로 docker compose yaml이 있다면 -f 옵션으로 지정할 수 있다.

예를 들어 파일 이름이 test.yml이라면 다음과 같다.

docker-compose -f test.yml up -d

docker-compose.yaml 파일이 내용이 올바르게 작성되었는지 검사하려면 다음과 같이 config 명령어를 사용하면 된다.

docker-compose config

위 docker-compose.yml 예제의 경우 Dockerfile의 image build를 따로 한 경우이다.
image build까지 같이하는 경우는 다음과 같다.

version: '3'

services:
  netflix-eureka-server:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        JAR_FILE: bluesky-cloud-parent/bluesky-cloud-netflix-eureka-server/target/bluesky-cloud-netflix-eureka-server-0.0.1-SNAPSHOT.jar
    ports:
      - '8761:8761'
    environment:
      - SPRING_PROFILES_ACTIVE=dockerdev

  config-server:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        JAR_FILE: bluesky-cloud-parent/bluesky-cloud-config-server/target/bluesky-cloud-config-server-0.0.1-SNAPSHOT.jar
    ports:
      - '8888:8888'
    environment:
      - SPRING_PROFILES_ACTIVE=dockerdev
    depends_on:
      - netflix-eureka-server

  admin-server:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        JAR_FILE: bluesky-cloud-parent/bluesky-cloud-admin-server/target/bluesky-cloud-admin-server-0.0.1-SNAPSHOT.jar
    ports:
      - '8889:8889'
    environment:
      - SPRING_PROFILES_ACTIVE=dockerdev
    depends_on:
      - netflix-eureka-server

위 경우 Dockerfile은 다음과 같다.

FROM openjdk:11-jdk
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

JAR_FILE이란 매개변수를 docker-compose.yml에서 넘겨서 빌드가 실행된 경우이다.
depend_on은 docker-compose up 실행 시 의존성 순서대로 서비스를 시작하고 docker-compose down 실행 시 역순서로 종료한다.
단순히 docker run 실행 순서를 지정할 뿐이고 해당 container가 ready 상태인지를 체크하지 않는다.
container 간 실행이 완료되었는지 여부를 확인하고 순차 실행을 하고 싶다면 이 문서를 참고하면 된다.

위에서 설명한 것처럼 빌드할 대상이 변경사항이 없는 경우 기존 container를 재사용한다.

따라서 빌드에 소요되는 시간도 매번 길지 않고 빠르게 재기동이 가능하다.

yaml 파일 설정 항목

위 2개의 예제에서 사용한 docker-compose.yml의 설정 항목은 다음과 같다.

항목 설명
version yaml 파일 포맷. 현재 docker-compose
services docker-compose로 생성할 container 항목을 정의
해당 항목 하위의 이름이 각각 container로 구현된다.
image image로 container를 생성하는 경우 사용
environment docker run의 --env -e 옵션과 동일
container 내부에서 사용할 환경 변수 지정
command container가 실행될 때 수행할 명령어
depends_on container의 의존관계 명시
명시된 container가 먼저 생성된 후 실행됨
ports docker run의 -p 옵션과 동일
container를 개방할 port 설정
build build 항목에 지정된 dockerfile에서 image를 build하여 container를 생성

이외에도 network 정의를 위한 항목이나 volume 정의를 위한 항목들이 있다.

반응형
profile

파란하늘의 지식창고

@Bluesky_

도움이 되었다면 광고를 클릭해주세요