Шпаргалка по работе с 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:
2. Создание собственного образа Docker.
3. Настройка локального репозитория для образов Docker и работа с ним.