Docker Compose

Введение в Compose

Compose — это инструмент для определения и запуска многоконтейнерных приложений Docker. С помощью Compose вы можете использовать файл YML для настройки всех сервисов, необходимых вашему приложению. Затем одной командой вы можете создать и запустить все сервисы из конфигурации файла YML.

Если вы ещё не понимаете настройку файла YML, сначала можете прочитатьУчебник по началу работы с YAML。

Три шага, используемые в Compose:

  • Используйте Dockerfile для определения окружения приложения.

  • Используйте docker-compose.yml, чтобы определить сервисы, составляющие ваше приложение, чтобы они могли работать вместе в изолированной среде.

  • Наконец, выполните команду docker-compose up, чтобы запустить всё приложение и начать его работу.

Пример конфигурации docker-compose.yml приведён ниже (параметры конфигурации см. ниже):

Пример

# пример конфигурации yaml
version
: '3'
services
:
  web
:
    build
: .
    ports
:
   - "5000:5000"
    volumes
:
   - .:/code
    - logvolume01:/var/log
    links
:
   - redis
  redis
:
    image
: redis
volumes
:
  logvolume01
: {}

Установка Compose

В Linux мы можем скачать его бинарный пакет с Github, чтобы использовать его. Адрес последнего выпуска:https://github.com/docker/compose/releases。

Выполните следующую команду, чтобы скачать текущий стабильный выпуск Docker Compose:

$ sudo curl -L "https://github.com/docker/compose/releases/download/v2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Чтобы установить другую версию Compose, замените v2.2.2.

Docker Compose размещён на GitHub и не очень стабилен.

Вы также можете быстро установить Docker Compose, выполнив следующую команду.

curl -L https://get.daocloud.io/docker/compose/releases/download/v2.4.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

Дайте бинарному файлу права на выполнение:

$ sudo chmod +x /usr/local/bin/docker-compose

Создайте символическую ссылку:

$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Проверьте, успешно ли прошла установка:

$ docker-compose version
cker-compose version 1.24.1, build 4667896b

ПримечаниеДля alpine требуются следующие пакеты зависимостей: py-pip, python-dev, libffi-dev, openssl-dev, gcc, libc-dev и make.

macOS

Docker Desktop для Mac и Docker Toolbox уже включают Compose и другие приложения Docker, поэтому пользователям Mac не нужно устанавливать Compose отдельно. Инструкции по установке Docker можно найти на страницеУстановка Docker в MacOS。

ПК с Windows

Docker Desktop для Windows и Docker Toolbox уже включают Compose и другие приложения Docker, поэтому пользователям Windows не нужно устанавливать Compose отдельно. Инструкции по установке Docker можно найти вУстановка Docker в Windows。


Использование

1. Подготовка

Создайте тестовый каталог.

$ mkdir composetest
$ cd composetest

В тестовом каталоге создайте файл с именем app.py и скопируйте и вставьте следующее содержимое:

Код файла composetest/app.py

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)


def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)


@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)

В этом примере redis — это имя хоста контейнера redis в сети приложения, а порт, используемый этим хостом, — 6379.

В каталоге composetest создайте ещё один файл с именемrequirements.txtсо следующим содержимым:

flask
redis

2. Создайте Dockerfile

В каталоге composetest создайте файл с именемDockerfileсо следующим содержимым:

FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run"]

Пояснение содержимого Dockerfile:

  • FROM python:3.7-alpine: Соберите образ на основе образа Python 3.7.
  • WORKDIR /code: Установите рабочую директорию в /code.
  • ENV FLASK_APP app.py
    ENV FLASK_RUN_HOST 0.0.0.0

    Задайте переменные окружения, используемые командой flask.

  • RUN apk add --no-cache gcc musl-dev linux-headers: Установите gcc, чтобы такие пакеты Python, как MarkupSafe и SQLAlchemy, могли компилироваться и работать быстрее.
  • COPY requirements.txt requirements.txt
    RUN pip install -r requirements.txt

    Скопируйте requirements.txt и установите зависимости Python.

  • COPY . .: Скопируйте текущий каталог из проекта (.) в рабочий каталог в образе (.).
  • CMD ["flask", "run"]: Команда выполнения по умолчанию для контейнера: flask run.

3. Создайте docker-compose.yml

В каталоге test создайте файл с именем docker-compose.yml и вставьте следующее содержимое:

Файл конфигурации docker-compose.yml

# конфигурация yaml
version
: '3'
services
:
  web
:
    build
: .
    ports
:
     - "5000:5000"
  redis
:
    image
: "redis:alpine"

Файл Compose определяет два сервиса: web и redis.

  • web: Веб-сервис использует образ, собранный из Dockerfile в текущем каталоге. Затем он привязывает контейнер и хост к открытому порту 5000. Этот пример сервиса использует порт 5000 по умолчанию веб-сервера Flask.
  • redis: Сервис redis использует публичный образ Redis из Docker Hub.

4. Используйте команды Compose для сборки и запуска вашего приложения

В каталоге test выполните следующую команду для запуска приложения:

docker-compose up

Если вы хотите запустить сервис в фоновом режиме, можно добавить-dПараметры:

docker-compose up -d

Справочник по директивам конфигурации yml

version

Укажите, какой версии Compose соответствует этот yml.

build

Укажите в качестве пути контекста образа сборки:

Например, для сервиса webapp укажите образ, собранный из контекстного пути ./dir/Dockerfile:

version: "3.7"
services:
  webapp:
    build: ./dir

Или, как объект с путём, указанным в context, и необязательными Dockerfile и args:

version: "3.7"
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1
      labels:
        - "com.example.description=Accounting webapp"
        - "com.example.department=Finance"
        - "com.example.label-with-empty-value"
      target: prod
  • context: путь контекста.
  • dockerfile: указывает имя файла Dockerfile, используемого для сборки образа.
  • args: Добавьте аргументы сборки, которые являются переменными окружения, доступными только во время процесса сборки.
  • labels: Задать метки для собранного образа.
  • target: Многоэтапная сборка, можно указать, какой этап собирать.

cap_add,cap_drop

Добавить или удалить возможности ядра хоста, доступные контейнеру.

cap_add:
  - ALL # 开启全部权限

cap_drop:
  - SYS_PTRACE # 关闭 ptrace权限

cgroup_parent

Указать родительскую группу cgroup для контейнера, что означает, что он унаследует ограничения ресурсов этой группы.

cgroup_parent: m-executor-abcd

command

Переопределить команду по умолчанию для запуска контейнера.

command: ["bundle", "exec", "thin", "-p", "3000"]

container_name

Указать пользовательское имя контейнера вместо сгенерированного имени по умолчанию.

container_name: my-web-container

depends_on

Задать зависимости.

  • docker-compose up: Запускает сервисы в порядке зависимостей. В следующем примере db и redis запускаются перед web.
  • docker-compose up SERVICE : автоматически включает зависимости SERVICE. В следующем примере docker-compose up web также создаст и запустит db и redis.
  • docker-compose stop: Останавливает сервисы в порядке зависимостей. В следующем примере web останавливается перед db и redis.
version: "3.7"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

Примечание: Сервис web не будет ждать полного запуска redis db, прежде чем запуститься.

deploy

Укажите конфигурацию, связанную с развертыванием и эксплуатацией сервиса. Полезно только в режиме swarm.

version: "3.7"
services:
  redis:
    image: redis:alpine
    deploy:
      mode:replicated
      replicas: 6
      endpoint_mode: dnsrr
      labels: 
        description: "This redis service label"
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s

Необязательные параметры.

endpoint_mode: Как получить доступ к сервисам кластера.

endpoint_mode: vip 
# Docker 集群服务一个对外的虚拟 ip。所有的请求都会通过这个虚拟 ip 到达集群服务内部的机器。
endpoint_mode: dnsrr
# DNS 轮询(DNSRR)。所有的请求会自动轮询获取到集群 ip 列表中的一个 ip 地址。

labels: Установите метки на сервисе. Вы можете использовать метки контейнера (конфигурации на том же уровне, что и deploy), чтобы переопределить метки в разделе deploy.

mode: Укажите режим, предоставляемый сервисом.

  • replicated: Реплицируйте сервис; реплицируйте указанный сервис на машины в кластере.

  • global: Глобальный сервис; сервис будет развернут на каждом узле кластера.

  • Диаграмма: На рисунке ниже желтые блоки показывают работу режима replicated, а серые блоки — работу режима global.

replicas:modeКогда для него установлено значение replicated, этот параметр требуется для настройки конкретного количества запущенных узлов.

resources: Настройте ограничения использования ресурсов для сервера. Например, в приведенном выше примере настройте процент CPU и использование памяти, необходимые для работы кластера redis, чтобы избежать исключений, вызванных чрезмерно высоким использованием ресурсов.

restart_policy: Настройте, как перезапускать контейнер при его завершении.

  • condition: необязательный параметр; возможные значения: none, on-failure или any (по умолчанию: any).
  • delay: Установите, сколько времени ждать перед перезапуском (по умолчанию: 0).
  • max_attempts: Количество попыток перезапуска контейнера. После превышения повторные попытки больше не предпринимаются (по умолчанию: повторять бесконечно).
  • window: Установите тайм-аут перезапуска контейнера (по умолчанию: 0).

rollback_config: Настройте, как служба должна откатываться в случае сбоя обновления.

  • parallelism: Количество контейнеров, откатываемых одновременно. Если установлено значение 0, все контейнеры откатываются одновременно.
  • delay: Время ожидания между откатами каждой группы контейнеров (по умолчанию: 0s).
  • failure_action: что делать, если откат не удался. Либо continue, либо pause (по умолчанию pause).
  • monitor: продолжительность наблюдения за тем, не завершилось ли обновление каждого контейнера неудачей (ns|us|ms|s|m|h) (по умолчанию 0s).
  • max_failure_ratio: допустимая доля сбоев во время отката (по умолчанию: 0).
  • order: порядок операций во время отката. Либо stop-first (последовательный откат), либо start (параллельный откат) (по умолчанию stop-first).

update_config: настройка того, как должен обновляться сервис; полезно для настройки поэтапных обновлений.

  • parallelism: количество контейнеров, обновляемых одновременно.
  • delay: время ожидания между обновлениями группы контейнеров.
  • failure_action: что делать, если обновление завершилось неудачей. Одно из значений: continue, rollback или pause (по умолчанию: pause).
  • monitor: продолжительность наблюдения за тем, не завершилось ли обновление каждого контейнера неудачей (ns|us|ms|s|m|h) (по умолчанию 0s).
  • max_failure_ratio: допустимая доля сбоев во время процесса обновления.
  • order: порядок операций во время отката. Либо stop-first (последовательный откат), либо start (параллельный откат) (по умолчанию stop-first).

Примечание: поддерживается только в V3.4 и выше.

устройства

Укажите список сопоставлений устройств.

devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"

dns

DNS-сервер; может быть одним значением или списком из нескольких значений.

dns: 8.8.8.8

dns:
  - 8.8.8.8
  - 9.9.9.9

dns_search

Пользовательские домены поиска DNS. Может быть одним значением или списком.

dns_search: example.com

dns_search:
  - dc1.example.com
  - dc2.example.com

entrypoint

Переопределить entrypoint контейнера по умолчанию.

entrypoint: /code/entrypoint.sh

Также может быть в следующем формате:

entrypoint:
    - php
    - -d
    - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
    - -d
    - memory_limit=-1
    - vendor/bin/phpunit

env_file

Добавить переменные среды из файла. Может быть одним значением или списком из нескольких значений.

env_file: .env

Также может быть в формате списка:

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

environment

Добавить переменные среды. Можно использовать массивы или словари, а также любые булевы значения. Булевы значения необходимо заключать в кавычки, чтобы парсер YML не преобразовал их в True или False.

environment:
  RACK_ENV: development
  SHOW: 'true'

expose

Открыть порты, но не сопоставлять их с хост-машиной; доступны только подключённым сервисам.

В качестве параметров можно указывать только внутренние порты:

expose:
 - "3000"
 - "8000"

extra_hosts

Добавьте сопоставления имён хостов. Аналогично docker client --add-host.

extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"

Вышеописанное создаст сопоставление IP-адреса и имени хоста в файле /etc/hosts внутри контейнера сервиса:

162.242.195.82  somehost
50.31.209.229   otherhost

healthcheck

Используется для проверки, работает ли служба docker исправно.

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
  interval: 1m30s # 设置检测间隔
  timeout: 10s # 设置检测超时时间
  retries: 3 # 设置重试次数
  start_period: 40s # 启动后,多少秒开始启动检测程序

image

Укажите образ, который запускает контейнер. Допустимы все следующие форматы:

image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id

logging

Конфигурация логирования для сервиса.

driver: Укажите драйвер логирования для контейнера сервиса. Значение по умолчанию — json-file. Доступны следующие три варианта:

driver: "json-file"
driver: "syslog"
driver: "none"

Только с драйвером json-file можно использовать следующие параметры для ограничения количества и размера логов.

logging:
  driver: json-file
  options:
    max-size: "200k" # 单个文件大小为200k
    max-file: "10" # 最多10个文件

При достижении лимита файлов старые файлы автоматически удаляются.

При использовании драйвера syslog можно использовать syslog-address, чтобы указать адрес приёма логов.

logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"

network_mode

Задаёт сетевой режим.

network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

networks

Настраивает сеть, к которой подключается контейнер, ссылаясь на записи в networks верхнего уровня.

services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2
networks:
  some-network:
    # Use a custom driver
    driver: custom-driver-1
  other-network:
    # Use a custom driver which takes special options
    driver: custom-driver-2

aliases: Другие контейнеры в той же сети могут использовать имя сервиса или этот псевдоним для подключения к сервису соответствующего контейнера.

restart

  • no: Это политика перезапуска по умолчанию. Контейнер не будет перезапущен ни при каких обстоятельствах.
  • always: Контейнер всегда перезапускается.
  • on-failure: Контейнер перезапускается только при аварийном завершении (ненулевой статус завершения).
  • unless-stopped: Всегда перезапускать контейнер при его завершении, но не учитывать контейнеры, которые уже были остановлены при запуске демона Docker.
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

Примечание: В режиме кластера swarm используйте вместо этого restart_policy.

secrets

Храните конфиденциальные данные, например пароли:

version: "3.1"
services:

mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
  secrets:
    - my_secret

secrets:
  my_secret:
    file: ./my_secret.txt

security_opt

Измените метку схемы контейнера по умолчанию.

security-opt:
  - label:user:USER   # 设置容器的用户标签
  - label:role:ROLE   # 设置容器的角色标签
  - label:type:TYPE   # 设置容器的安全策略标签
  - label:level:LEVEL  # 设置容器的安全等级标签

stop_grace_period

Укажите, сколько ждать перед отправкой SIGKILL для остановки контейнера, если он не может обработать SIGTERM (или любой сигнал из stop_signal).

stop_grace_period: 1s # 等待 1 秒
stop_grace_period: 1m30s # 等待 1 分 30 秒 

Время ожидания по умолчанию — 10 seconds.

stop_signal

Задайте альтернативный сигнал для остановки контейнера. По умолчанию используется SIGTERM.

В следующем примере SIGUSR1 используется вместо SIGTERM для остановки контейнера.

stop_signal: SIGUSR1

sysctls

Задайте параметры ядра в контейнере; можно использовать формат массива или словаря.

sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0

tmpfs

Смонтировать временную файловую систему внутри контейнера. Может быть одним значением или списком из нескольких значений.

tmpfs: /run

tmpfs:
  - /run
  - /tmp

ulimits

Переопределить ulimit контейнера по умолчанию.

ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000

volumes

Смонтировать тома данных или файлы хоста в контейнер.

version: "3.7"
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "/localhost/data:/var/lib/postgresql/data"
Другие расширения