Docker Compose
Docker Compose - это инструмент для определения и управления многоконтейнерными приложениями с помощью файла конфигурации в YAML-формате. С помощью Docker Compose вы можете описать все компоненты вашего приложения, их зависимости, сети и объединить их в одном файле, что делает развертывание и управление приложением проще и более структурированным.
Основные преимущества Docker Compose:
- Определение инфраструктуры как кода Вы можете определить структуру и настройки своего приложения в YAML-файле, что позволяет использовать подход "инфраструктура как код" (Infrastructure as Code). Это упрощает документирование и повторяемость развертывания.
- Многоконтейнерные приложения Docker Compose позволяет определить и управлять несколькими контейнерами, которые взаимодействуют друг с другом.
- Сети и зависимости Docker Compose автоматически создает сети для взаимодействия между контейнерами, а также управляет зависимостями между компонентами.
- Упрощение команд Вместо того чтобы запускать отдельные команды для создания и запуска каждого контейнера, вы можете использовать одну команду
docker-compose up, чтобы развернуть всё приложение.
Файл Docker Compose (Docker-compose.yml) - это YAML-файл, который определяет структуру и конфигурацию многоконтейнерного приложения. В этом файле вы описываете различные сервисы, сети, тома и другие компоненты, необходимые для вашего приложения. Вот основные элементы структуры файла Docker Compose:
---
services: # Перечень создаваемых сервисов (контейнеров)
service_name: # Имя сервиса
image: image_name:tag # Образ для контейнера
pull_policy: always # Политика скачивания новых версий образа, например для тега latest
restart: always # осуществляет перезапуск сервиса при его сбое
depends_on: # будет ждать запуска других контейнеров
- service-name
environment: # передаем в контейнер переменные среды
- env=primer
volumes:
- vol_name:/dir
- docker-dir # здесь указывается полный путь к папке внутри контейнера которая не будет синхронизироваться с хостом
- host-dir:docker-dir
# Другие настройки для контейнера
app: # произвольное имя сервиса
build: ./app # указывает путь к докер-файлу из которого будет создан докер-образ из которого будет создан контейнер
ports: # указываем какие порты мы хотим пробросить на хост-компьютер
- 'host-port:container-port'
networks: # Описание сетей
network_name: # Имя сети
# Настройки для сети
volumes: # Описание томов
volume_name: # Имя тома, нужен для хранения общих данных и сохранения данных при остановке работающих контейнеров
# Настройки для тома
Основные команды для запуска docker-compose:
docker compose up -d - запускает докер манифест
docker compose down - останавливает и удаляет контейнеры развернутые манифестом
docker compose up --build - принудительно запускает пересборку образов, с последующим запуском контейнеров.
docker compose stop <service_name> - остановить контейнер сервиса.
docker compose rm <service_name> - удалить контейнер сервиса.
docker compose start <service_name> - запустить контейнер сервиса.
docker compose up -d --build <service_name> - пересобрать и запустить контейнер сервиса.
docker compose pull && docker compose up -d --force-recreate - подгружает последние версии образов (если, например указан тег latest) и пересоздает контейнеры.
Использование нескольких docker-compose файлов
Можно использовать несколько конфигурациооных файлов, при этом Compose комбинирует их в единую конфигурацию. Compose собирает конфигурацию в том порядке в котором указаны файлы. Последующие файлы добавляются к предыдущим. Т.е. в базовом файле docker-compose.yml задаются основные настроики запускаемой конфигурации, а в дополнительном файле docker-compose.add1.yml будут заданы дополнительные настройки, актуальные для определенного окружения, а в другом файле, например: docker-compose.add2.yml будут заданы настройки актуальные для другого окружения. Важно понимать как именно Compose собирает итоговую конфигурацию: беруться настройки из первого указанного докер-манифеста, к ним добавляются настройки из второго манифеста и т.д., настроики лишь добавляются, настройки определенные в предыдущих манифестах сохраняются и не могут быть переопределены в последующих.
Пример:
# собираем одно окружение для prod
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -p prod
# собираем другое окружения для dev
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -p dev
Флаг -f является необязательным. Если вы не используете данный флаг в командной строке, Compose проверяет текущую директорию и родительские в поисках файлов docker-compose.yml и docker-compose.override.yml. Должен быть хотя бы файл docker-compose.yml. Если оба файла присутствуют в одном каталоге, Compose комбинирует оба файла в единую конфигурацию. Конфигурационный файлdocker-compose.override.yml применяется поверх файла docker-compose.yml.
Каждая конфигурация имеет имя проекта. С помощью флага -p, вы можете задать имя проекта. Если вы не используете данный флаг, Compose использует имя каталога с проектом
Переменные окружения Compose
Подстановка переменных среды в Compose файлах
В оболочке можно использовать переменные среды для заполнения значений внутри файла Compose:
Задание переменных окружения в контейнерах
Можно задать переменные окружения в контейнере сервиса с помощью ключевого слова environment, также как и в случае docker run -e VARIABLE=VALUE ...:
grafana:
environment:
- GF_SECURITY_ADMIN_USER=${ADMIN_USER}
- GF_SECURITY_ADMIN_PASSWORD=${ADMIN_PASSWORD}
Передача переменных окружения в контейнеры
Можно передать переменные окружения из вашей оболочки прямо в контейнеры сервиса с помощью ключевого слова environment но не задавая значение, так же как и в docker run -e VARIABLE ...:
grafana:
environment:
- GF_SECURITY_ADMIN_USER
- GF_SECURITY_ADMIN_PASSWORD
# В этом случае: Значение переменных в контейнере будет взято из значения тех же переменных в оболочке из которой был запущен Compose.
Опция env_file
Можно передать несколько переменных окружения из внешнего файла в контейнеры сервиса с помощью опции env_file, также как и в docker run --env-file=FILE ...:
grafana:
env_file:
- ./grafana/grafana-variables.env
Установка переменных окружения с помощью команды docker-compose run
docker-compose run -e VAR_NAME=VAR_VALUE service1 service2
docker-compose run -e OTHER_VAR_NAME=VAR_VALUE service3
Файл .env
Можно установить значения по умолчанию для любых переменных среды, указанных в Compose файле или использовать для настройки Compose файл среды с именем .env.
Файл .env располагается в корне проекта вместе с файлом docker-compose.yml.
Значения из файла .env имеют наименьший приоритет и могут быть переопределены, например: заданием переменной из оболочки.
Использование секретов с Docker Compose
Секреты — это конфиденциальные данные, которые можно передавать контейнерам, не включая их в кодовую базу или переменные среды. Docker обеспечивает их безопасность, предоставляя доступ только тем контейнерам, которые их запрашивают.
Docker Compose предоставляет возможность использовать секреты без необходимости использования переменных среды. Если использовать секреты в качестве переменных среды, можно создать потенциальную уязвимость. Сервисы могут получить доступ к секретам только в том случае, если это явно предоставлено атрибутом secrets в элементе верхнего уровня служб.
Переменные среды часто доступны всем процессам, и отследить доступ может быть сложно. Они также могут быть выведены в журналы при отладке ошибок без вашего ведома. Использование секретов снижает эти риски.
Использование секретов в compose-файлах
Помещение секрета в контейнер — это двухэтапный процесс. Сначала необходимо определить секрет с помощью элемента secrets верхнего уровня в Compose-файле. Затем добавить в определения служб атрибут secrets. Compose предоставляет доступ к секретам на основе настроек каждой службы.
В отличие от других методов, этот позволяет осуществлять детальный контроль доступа в контейнере служб с помощью стандартных разрешений файловой системы
Определение секретов верхнего уровня. Источником секрета является файл или переменная среды.
- file: Секрет создается с содержимым файла по указанному пути.
- environment: Секрет создается со значением переменной среды.
- При этом секрет передаетсявнутрь контейнера в качестве файла по следующему пути
/run/secrets/<secret_id>
Пример
# Определяем какие секреты будут доступны и в каких файлах они хранятся
secrets:
db_password:
enviroment: DB_PASSWORD # секретная переменная среды
db_root_password:
file: /path/to/secret_dir/db_root_password.txt # секретная директория
volumes:
db_data:
services:
db:
image: mysql:latest
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password # указываем сервису где искать секрет
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD_FILE: /run/secrets/db_password # указываем сервису где искать секрет
secrets: # определяем какие секреты доступны этому сервису
- db_root_password
- db_password
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_password # указываем сервису где искать секрет
secrets: # определяем какие секреты доступны этому сервису
- db_password