Шпаргалка по работе с docker-compose

Обновлено Обновлено: Опубликовано Опубликовано:

В данной инструкции мы приведем различные примеры по работе с docker-compose без подробного описания принципа работы. Данный материал можно использовать в качестве шпаргалки.

Базовый шаблон

В первую очередь, предлагаю заготовку для docker-compose файла, на основе которой можно начинать писать свой сценарий для docker.

Создаем файл для работы с контейнерами:

vi docker-compose.yml

services:

  <srv_name>:
    image: <image_name>
    container_name: <container_name>
    hostname: <hostname>
    restart: unless-stopped
    environment:
      TZ: "Europe/Moscow"
    networks:
      - default

networks:
  default:
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16

* где:

  • services — основной раздел, где мы будем создавать и описывать наши сервисы (контейнеры docker). В данном примере сервис один. Для добавления еще одного добавляем еще строчки <srv_name>.
    • <srv_name> — название для нашего сервиса, на основе которого будет создан контейнер.
    • image — имя образа, который будет использоваться для создания контейнера.
    • container_name — имя, которое получен созданный контейнер.
    • hostname — имя хоста внутри контейнера.
    • restart — поведения контейнера при падении. В нашем примере мы указываем на необходимость автоматической перезагрузки, за исключением случаев, когда мы его сами остановили командой stop.
    • environment — задаем переменные окружения. В нашем примере только одна, которая указывает на часовой пояс (московское время).
    • networks — привязываем наш контейнер к сети. Опционально, но лучше определять самому подсеть. Это упрощает настройку некоторых сервисов, например, мы можем ограничить доступ для определенных подсетей и не желательно, чтобы подсети задавалась случайным образом.
  • networks — описание для сети. В нашем примере используются стандартные настройки, но указывается конкретная подсеть 172.28.0.0/16.

Сервисы

В данном разделе рассмотрим примеры настроек сервисов (контейнеров). Синтаксис:

services:
  <имя сервиса>:
    <настройки сервиса>

1. Создание контейнера из готового образа. Образ указывается с помощью директивы image:

    image: nginx

* в данном примере будет взят образ nginx для поднятия контейнера.

2. Сборка контейнера из Dockerfile. Для этого используем опцию build:

    build:
      context: ./web-server/
      args:
        buildno: 22042001

* где:

  • build — указание на необходимость сборки из Dockerfile. Пример создания последнего читайте в инструкции Создание собственного образа Docker.
  • context — путь, где нужно искать Dockerfile относительно места, где находится docker-compose файл.
  • buildno — номер для сборки.

3. Проброс папок (volumes). Настраивается с помощью опции volumes:

    volumes:
      - /data/mysql:/var/lib/mysql

* в нашем примере мы смонтируем локальный каталог /data/mysql на хосте внутрь контейнера в качестве каталога /var/lib/mysql.

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

    volumes:
      - /:/rootfs:ro

4. Работа с портами. Рассмотрим несколько вариантов работы с портами.

а) Ports (внешняя публикация). С помощью данной опции мы можем указывать, на каких портах должен слушать контейнер и на какие порты должны пробрасываться запросы:

    ports:
      - 8080:80

* в данном примере наш контейнер будет слушать запросы на порту 8080 и передавать их внутрь контейнера на порт 80.

Или можно прописать так:

    ports:
      - 80

* в этом примере будет настроен проброс на порт 80. Внешний порт будет выбран docker автоматически.

б) Expose (внутрення публикация). Данная опция задает порт, на котором должно слушать приложение внутри контейнера, но проброса с внешнего адреса не будет — отправить запрос по сети на данный порт можно с другого контейнера:

    expose:
      - 7000

5. Переменные окружения. В нашей универсальной заготовке мы уже использовали одну системную переменную:

    environment:
      TZ: "Europe/Moscow"

Чтобы передать несколько переменных, просто их перечисляем:

    environment:
      TZ: "Europe/Moscow"
      MYSQL_ROOT_PASSWORD=password

Для каждого приложения есть свой набор системных переменных, которые оно понимает и интерпретирует. Например, MYSQL_ROOT_PASSWORD поймет СУБД и установит значение в качестве пароля для пользователя root.

Также системные переменные можно передать не в сценарии docker-compose, а в файле .env — просто создадим этот файл в одной директории с файлом docker-compose.yml:

vi .env

MYSQL_ROOT_PASSWORD=secret
MYSQL_PWD=secret

6. Зависимости для контейнеров. Мы можем указать с помощью опции depends_on, от какого контейнера зависит сервис:

    depends_on:
      - db

* в конкретном примере, контейнер не запустится, пока не поднимется db.

7. Переопределить команду. С помощью директивы command мы можем переопределить команду для запуска, например:

    command: [ "redis-server", "/usr/local/etc/redis/redis.conf" ]

* в данном примере мы запустим redis-server с альтернативным конфигурационным файлом.

Или можно написать так:

    command:
      - redis-server
      - /usr/local/etc/redis/redis.conf

Но если нам понадобиться запустить несколько последовательных команд, рабочий вариант с использованием bash:

    command: bash -c "yarn install && yarn start"

или если в контейнере нет bash:

    command: sh -c "yarn install && yarn start"

8. Метки. С помощью опции labels мы можем указывать дополнительную информацию для ориентирования или фильтров при поиске контейнеров:

    labels:
      MAINTAINER: ${MAINTAINER_EMAIL}
      SITE_URL: ${SITE_URL}

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

9. Пользователь. Директива user позволяет задать конкретного пользователя, от которого будет запускаться и работать контейнер:

    user: root

10. Домашняя директория. Определяет положение по умолчанию, откуда будут выполняться команды.

    working_dir: /var/www/app

Healthcheck

Данная директива, хоть и является частью сервиса, мы рассмотрим ее в отдельном разделе. Синтаксис:

services:
  <имя сервиса>:
    ...
    healthcheck:
      test: <script>
      interval: <interval>
      timeout: <timeout>
      retries: <retries>

* где:

  • test — наш скрипт, который должен вернуть 0, если все хорошо, или 1 — если все плохо.
  • interval — как часто запускать проверку.
  • timeout — как долго нужно ждать ответа.
  • retries — сколько раз тест должен вернуть отрицательный результат, чтобы контейнер перешел в состояние «unhealthy».

1. Проверка работы веб-портала. Рассмотрим пример, когда сайт при правильной работы должен возвращать слово works:

    healthcheck:
      test: curl -s http://127.0.0.1 | grep works
      interval: 30s
      timeout: 2s
      retries: 10

* в данном примере мы запросим у нашего сервера страницу по http и выведем строку, в которой есть слово works. Если такой строки не найдется, команда вернет код 1.

2. Проверка СУБД mysql. Проверку можно выполнить с помощью запроса SELECT 1. В композ-файле это выглядит так:

    healthcheck:
      test: ["CMD", "mysql" ,"-h", "mysql", "-P", "3306", "-u", "root", "-e", "SELECT 1", "cache"]
      interval: 30s
      timeout: 2s
      retries: 10

Networks

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

Список сетей, созданных для docker можно увидеть командой:

docker network ls

Получить подробную информацию по сети можно командой:

docker network inspect <имя сети>

1. Указать определенную подсеть. Задается с помощью опции subnet в отдельной секции networks. В последней мы создаем конфигурацию для определенной сети (в данном примере, default). Для конкретного сервиса мы также задаем привязку к созданной сети default в подразделе networks:

services:

  <srv_name>:
    ...
    networks:
      - default

networks:
  default:
    ipam:
      driver: default
      config:
        - subnet: 172.28.0.0/16

* где 172.28.0.0/16 — подсеть, в которой будут работать все контейнеры, которые привязаны к созданной сети default.

2. Алиасы. Данная настройка позволит видеть контейнеры по альтернативным именам (по умолчанию, они обнаруживаются по имени контейнера). Настройка указывается в подразделе networks сервиса:

services:

  <srv_name>:
    ...
    networks:
      default:
        aliases:
          - <alternative_name>

* в данном примере наш контейнер будет также резолвиться по имени <alternative_name>.

3. Внешняя сеть. Если необходимо, чтобы наши контейнеры могли видеть по сети другие контейнеры, создаем сеть external:

services:

  <srv_name>:
    ...
    networks:
      - dnet

networks:
  dnet:
    external:
      name: dnet

4. Статические IP-адреса. По docker идеологии все контейнеры должны получать IP-адреса автоматически. Но все же, метод для указания контейнерам статических адресов предусмотрен. Рассмотрим на примере:

services:

  <srv_name>:
    ...
    networks:
      vpcbr:
        ipv4_address: 172.28.0.2

networks:
  vpcbr:
    driver: bridge
    ipam:
     config:
       - subnet: 172.28.0.0/24
         gateway: 172.28.0.1

* в нашем примере будет создана подсеть 172.28.0.0/24, а контейнеру будет присвоен адрес 172.28.0.2.

5. Добавить сопоставление имя - IP-адрес (на подобие локального файла hosts). С помощью данной настройки мы можем указать отдельно для контейнеров, в какой IP-адрес должен разрешаться определенный хост. Задается с помощью директивы extra_hosts:

services:

  <srv_name>:
    ...
    extra_hosts:
      foo: 1.2.3.4
      bar: 5.6.7.8

* в данном примере имени foo будет соответствовать адрес 1.2.3.4, а bar — 5.6.7.8.

Запуск docker-compose

Рассмотрим различные примеры выполнения команды docker-compose.

1. Посмотреть версию:

docker-compose --version

2. Создание и запуск контейнеров:

docker-compose up -d

* напомним, что в текущем каталоге находится созданный файл с названием docker-compose.yml.

С указанием альтернатнативного файла docker-compose.

docker-compose -f /foo/bar/other-docker-compose.yml up -d

3. Перечитать файл docker-compose:

docker-compose up -d

* на самом деле, команда такая же, как для запуска. Система если определит, что есть изменения, пересоздаст контейнер.

Перечитать и пересобрать контейнеры, если есть инструкция build:

docker-compose up -d --build

4. Остановить контейнеры.

Только остановить контейнеры:

docker-compose down

Остановить контейнеры с удаление данных (в volumes):

docker-compose down --volumes

Возможные ошибки

Network <net-name>_default  Error

При попытке запустить compose получаем ошибку:

 Network <net-name>_default  Error
failed to create network <net-name>_default: Error response from daemon: could not find an available, non-overlapping IPv4 address pool among the defaults to assign to the network

Причина: при запуске композа автоматически создается сеть с префиксом _default. Данная ошибка означает, что такую сеть не удалось создать, так как существует лимит на пулы IP-адресов и данный лимит был исчерпан.

Решение: быстрее всего выполнить чистку docker от неиспользуемых сетей. Для этого выполняем команду:

docker network prune

Читайте также

Другие инструкции, связанные с Docker:

1. Установка Docker на Linux.

2. Создание собственного образа Docker.

3. Настройка локального репозитория для образов Docker и работа с ним.

# DevOps # Виртуализация
Дмитрий Моск — частный мастер
Была ли полезна вам эта инструкция?

Да            Нет