[Docker] Compose 구성과 사용법

[Docker] Compose 구성과 사용법

안녕하세요? 정리하는 개발자 워니즈입니다. 오늘은 docker의 compose구성법에 대해서 정리를 해보려고 합니다.
만약 여러분이 앱컨테이너와 데이터베이스 컨테이너의 실행 순서를 지켜서 실행해야한다고 생각해보세요. 반드시 데이터베이스 컨테이너를 실행한 다음에 앱 컨테이너를 실행해야 합니다. 그렇지 않으면 앱 컨테이너에서 데이터베이스 컨테이너를 찾을 수 없기 때문이죠. 깜박하고 앱 컨테이너부터 실행했다면? 종료하고 데이터베이스 컨테이너 실행하고, 다시 앱 컨테이너를 실행하는 불편함이 있죠.

도커 컴포즈를 사용하면 컨테이너 실행에 필요한 옵션을 docker-compose.yml이라는 파일에 적어둘 수 있고, 컨테이너 간 실행 순서나 의존성도 관리할 수 있습니다.

1. docker-compose.yml 파일

docker-compose.yml은 장황한 도커 실행 옵션을 미리 적어둔 문서라고 볼 수 있습니다. 프로젝트 루트에 파일을 만들고, 다음 내용을 붙여 넣습니다.

version: '3'

services:
  db:
    image: postgres
    volumes:
      - ./docker/data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=sampledb
      - POSTGRES_USER=sampleuser
      - POSTGRES_PASSWORD=samplesecret
      - POSTGRES_INITDB_ARGS=--encoding=UTF-8

  django:
    build:
      context: .
      dockerfile: ./compose/django/Dockerfile-dev
    environment:
      - DJANGO_DEBUG=True
      - DJANGO_DB_HOST=db
      - DJANGO_DB_PORT=5432
      - DJANGO_DB_NAME=sampledb
      - DJANGO_DB_USERNAME=sampleuser
      - DJANGO_DB_PASSWORD=samplesecret
      - DJANGO_SECRET_KEY=dev_secret_key
    ports:
      - "8000:8000"
    command: 
      - python manage.py runserver 0:8000
    volumes:
      - ./:/app/

이제 한줄씩 확인해보면서 정리 하도록 해보겠습니다.

  1. version
    version: '3'
    

    docker-compose.yml 파일의 첫 줄에는 파일 규격 버전을 적습니다. 파일의 규격에 따라 지원하는 옵션이 달라지는데, “3”이라만 적으면 3으로 시작하는 최신 버전을 사용한다는 의미입니다. (파일 규격 버전에 따른 자세한 내용은 compose 파일의 버전과 호환성을 안내한 공식 문서를 참고하세요.)

  2. services
    services:
    

    이 항목 밑에 실행하려는 컨테이너들을 정의합니다. 컴포즈에서는 컨테이너 대신 서비스라는 개념을 사용합니다.

  3. db
    services:
     db:
    

    postgres 서비스의 이름을 db로 정하였습니다.

  4. image
    services:
     db:
       image: postgres
    

    db 서비스에서 사용할 도커 이미지를 적습니다. 여기서는 dockerhub의 공식 postgres 이미지를 사용하였습니다.

  5. volumes
    services:
     db:
       volumes:
         - ./docker/data:/var/lib/postgresql/data
    

    docker run으로 db 컨테이너를 실행할 때 –volume 옵션을 사용하여 데이터베이스의 데이터를 로컬 컴퓨터에 저장했던 부분과 같습니다. 다만 docker-compose.yml의 volumes에는 상대 경로를 지정할 수 있어서 편리합니다.

    docker run으로 db 컨테이너를 실행할 때와 마찬가지로, 프로젝트 루트 아래의 docker/data 디렉터리에 데이터를 저장하기로 했습니다.

  6. environment

    services:
     db:
       environment:
         - POSTGRES_DB=sampledb
         - POSTGRES_USER=sampleuser
         - POSTGRES_PASSWORD=samplesecret
         - POSTGRES_INITDB_ARGS=--encoding=UTF-8
    

    docker run 명령어의 -e 옵션에 적었던 내용들입니다. 마지막의 POSTGRES_INITDB_ARGS 부분이 추가되었는데, 데이터베이스 서버의 인코딩을 UTF-8로 설정하기 위함입니다.

  7. django

    services:
     django:
    

    앱 서비스의 이름은 django로 지정하였습니다.

  8. build

    services:
     django:
       build:
         context: .
         dockerfile: ./compose/django/Dockerfile-dev
    

    db 서비스와 달리 앱 서비스는 특정 이미지 대신 build 옵션을 추가합니다.

    context는 docker build 명령을 실행할 디렉터리 경로라고 보시면 됩니다.

    dockerfile에는 ‘개발용’ 도커 이미지를 빌드하는 데 사용할 Dockerfile을 지정하면 됩니다. Dockerfile-dev 파일에서는 (운영용 Dockerfile과는 달리) 소스코드를 컨테이너에 넣지 않습니다.

  9. ports

    services:
     django:
       ports:
         - "8000:8000"
    

    docker run 명령어의 -p 옵션에 해당하는 부분입니다.

  10. command

    services:
      django:
        command:
          - python manage.py runserver 0:8000
    

    docker run으로 앱 컨테이너를 실행할 때 가장 마지막에 적었던 명령어 부분입니다.

2. 도커 컴포즈의 주요 명령어

  • up -d
docker-compose.yml 파일의 내용에 따라 이미지를 빌드하고 서비스를 실행합니다. 자세한 진행 과정은 다음과 같습니다.

서비스를 띄울 네트워크 설정
필요한 볼륨 생성(혹은 이미 존재하는 볼륨과 연결)
필요한 이미지 풀(pull)
필요한 이미지 빌드(build)
서비스 의존성에 따라 서비스 실행
up 명령에 사용할 수 있는 몇 가지 옵션도 존재합니다.

-d: 서비스 실행 후 콘솔로 빠져나옵니다. (docker run에서의 -d와 같습니다.)
–force-recreate: 컨테이너를 지우고 새로 만듭니다.
–build: 서비스 시작 전 이미지를 새로 만듭니다.

  • ps

현재 환경에서 실행 중인 각 서비스의 상태를 보여줍니다.

$ docker-compose ps
        Name                       Command               State           Ports
--------------------------------------------------------------------------------
djangosample_db_1       /docker-entrypoint.sh postgres   Up      5432/tcp
djangosample_django_1   /bash -c python manage.py        Up      0.0.0.0:8000->8000/tcp
  • stop, start

서비스를 멈추거나, 멈춰 있는 서비스를 시작합니다.

$ docker-compose stop
Stopping djangosample_django_1 ...
Stopping djangosample_db_1 ...

$ docker-compose start
Starting db ... done
Starting django ... done
  • down

서비스를 지웁니다. 컨테이너와 네트워크를 삭제하며, 옵션에 따라 볼륨도 지웁니다.

$ docker-compose down --volume
Removing myproject_django_1 ... done
Removing myproject_db_1 ... done
Removing network djangosample_default
Removing volume django_sample_db_dev

–volume: 볼륨까지 삭제합니다.

  • exec

실행 중인 컨테이너에서 명령어를 실행합니다. 자동화된 마이그레이션용 파일 생성이나 유닛 테스트, lint 등을 실행할 때 사용합니다.*

  • 비슷한 명령으로 run이 존재합니다. run은 새 컨테이너를 만들어서 명령어를 실행합니다. docker run과 마찬가지로 –rm 옵션을 추가하지 않으면, 컨테이너가 종료된 후에도 삭제되지 않습니다. (이런 이유 때문에 개인적으로는 exec를 선호하지만, 컨테이너에서 추천하는 방식은 사실 run입니다.)
$ docker-compose exec django ./manage.py makemigrations
...
$ docker-compose exec node npm run test
> expresssample@0.1.0 test /www/service
> mocha $(find test -name '*.spec.js')
...
  • logs

서비스의 로그를 확인할 수 있습니다. logs 뒤에 서비스 이름을 적지 않으면 도커 컴포즈가 관리하는 모든 서비스의 로그를 함께 보여줍니다.

$ docker-compose logs django
Attaching to djangosample_django_1
django_1     | System check identified no issues (0 silenced).
django_1     | February 13, 2017 - 16:32:28
django_1     | Django version 1.10.4, using settings 'djangosample.settings'
django_1     | Starting development server at http://0.0.0.0:8000/
django_1     | Quit the server with CONTROL-C.

-f: 지금까지 쌓인 로그를 다 보여준 후에도 셸로 빠져나오지 않고, 로그가 쌓일 때마다 계속해서 출력합니다.

3. 예시

필자에게 업무중 주어진 미션이 각종 tool 들을 업그레이드 버전으로 설치하는 것이였다. 그런데 리눅스를 다뤄보신 분들은 알겠지만, 업그레이드라는게 yum 으로 쉽사리 설치가 되면 좋겠지만 각종 설정 파일들부터 복원 계획도 다 갖고 있어야 한다.

필자의 프로젝트에서는 grafana, zabbix, rundeck, kibana, eleasticsearch 등 다양한 도구들을 활용하고 있는데, 업그레이드를 하면서 지속적으로 기존 시스템에 영향을 주지 않는 범위내에서 해보고 싶었고, docker가 제격이라고 생각하게 되었다.

다음의 시나리오대로 grafana를 업그레이드 해봤습니다.

  1. 기존 파일 백업
    - /var/lib/grafana 경로에서 데이터 백업
    cp -r grafana grafana_bak 
    
    그라파나의 데이터베이스 경로
    
  2. 도커 컨테이너 실행

    공식 문서에 보면, 다음과 같이 도커를 실행하라고 명시되어있다.

    $ docker run \
     -d \
     -p 3000:3000 \
     --name=grafana \
     -e "GF_SERVER_ROOT_URL=http://grafana.server.name" \
     -e "GF_SECURITY_ADMIN_PASSWORD=secret" \
     grafana/grafana
    

    위의 명령어를 보시면 알겠지만,

    -d : 데몬(백그라운드) 실행

    -p : 포트 포워딩

    –name : 컨테이너 네임 명시

    -e : 환경 변수 : 그라파나 configure에 명시되어있어서 없어도도.ㅁ

    grafana/grafana : 이미지 명시 (최신 이미지 가져옴) -> grafana/grafana:5.1.0 특정 버전 명시가능

    필요한 플러그인 업데이트

    *실제로 설치하고 난뒤, Zabbix plugin for Grafana 가 에러가 발생하여, 컨테이너 내부에서 업데이트를 하였습니다

    grafana-cli plugins install 
    
  3. 컴포즈 구성으로 변경
    version: "2.1"
    services:
     grafana:
         image: grafana
         restart: always
         container_name: grafana
         volumes:
           - "/var/lib/grafana:/var/lib/grafana"
         expose:
           - 3000
         ports:
           - "3000:3000"
    

    위의 docker 명령어를 명시해 놓은 compose 파일로 간단하게 실행이 가능합니다.

  4. 컨테이너 실행

    docker-compose up -d
    

블로그 워니즈
워니즈 블로그

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다