Руководство по Docker Compose
Docker Compose точно пригодится, если для работы приложения нужно соединить в цепочку несколько сервисов. Например, один сервис отвечает за работу базы данных, другой — за авторизацию пользователей, третий — за серверный рендеринг и так далее.
Разбивать приложение на микросервисы можно до бесконечности. А наоборот, собирать из этих блоков единое работающее приложение помогает Docker Compose.
Содержание:
1. Что такое Docker Compose
2. Отличия между Docker и Docker Compose
3. Возможности Docker Compose
4. Области применения
5. Установка и использование Docker Compose в Ubuntu
6. Подробнее о структуре docker-compose.yaml
7. Примеры проектов с Docker Compose
8. Практика: простое приложение на Django/PostgreSQL
Заключение
1. Что такое Docker Compose
Docker Compose — инструмент для запуска и управления мультиконтейнерными приложениями. Он помогает создать изолированную среду (песочницу), в которой содержатся все необходимые зависимости.
Конфигурация такого приложения описывается в файле YAML. Запустить приложение, ранее собранное в контейнер, можно одной командой.
2. Отличия между Docker и Docker Compose
Docker управляет отдельными сервисами, из которых состоит приложение.
Docker Compose управляет несколькими контейнерами, которые входят в состав приложения. Возможности те же, что и у Docker. Но можно выстраивать более комплексные системы взаимодействия.
3. Возможности Docker Compose
Несколько изолированных сред на одном хосте
Вы можете создавать несколько сред окружения на одном хосте, используя название проекта в различных контекстах:
- Создать на одном хосте несколько копий одного и того же окружения.
- Установить название проекта с номером сборки для исключения конфликта версий на сервере.
- Изолировать разные проекты на хосте, которые могут использовать сервисы с одинаковыми названиями.
По умолчанию названием проекта становится имя его корневой директории. Но его можно задать самостоятельно, используя опцию -p или переменную окружения COMPOSE_PROJECT_NAME
.
Защита данных тома при создании контейнеров
Docker Compose по умолчанию защищает тома, которые используются сервисами. Если от предыдущего запуска остались тома, то при выполнении команды docker-compose up
данные из них копируются в новые тома.
Пересоздаются только измененные контейнеры
Compose кэширует конфигурацию, которая была использована для создания контейнера. Если перезапустить контейнер без изменений, то будут использованы существующие файлы. Такое повторное использование обеспечивает быстрое внесение изменений в проект.
Переменные и перемещение между средами
Compose поддерживает переменные в файле docker-compose
. Вы можете использовать их для настройки конфигурации под разные среды и/или пользователей. Также можно создать несколько файлов и расширять их с помощью поля extends
в docker-compose
.
4. Области применения
Среды разработки
Запуск и взаимодействие с приложением в изолированной среде — важная часть разработки. Compose помогает создать необходимое окружение и взаимодействовать с ним через интерфейс командной строки.
Вы описываете все зависимости службы в файле docker-compose
— базы данных, веб-службы API, очереди, кеши. Создать и запустить один или несколько контейнеров можно одной командой — docker-compose up
.
Такой подход помогает значительно ускорить процесс разработки. Не нужны многостраничные инструкции, вся конфигурация укладывается в один небольшой файл.
Автоматизированные среды тестирования
Для непрерывного проведения автоматизированных тестов нужна изолированная среда. Docker Compose обеспечивает удобный процесс создания и удаления систем для тестирования. Все действия можно уложить в три простые команды:
docker-compose up -d ./run_tests docker-compose down
В этом примере вы запускаете приложение, выполняете необходимые тесты и останавливаете выполнение контейнера.
Развертывание хоста
Традиционно Compose больше используется для разработки и тестирования. Но с каждым новым релизом в нем появляется больше инструментов для деплоя.
5. Установка и использование Docker Compose в Ubuntu
На Linux Docker Compose нужно устанавливать отдельно. Для его работы требуется сам Docker. Его установка подробно описана в документации — например, вот инструкция для Ubuntu.
Прежде чем устанавливать Docker Compose, посмотрите в репозитории на GitHub, какая у него последняя версия. Например, сейчас это v2.2.2.
Чтобы скачать последний релиз, запустите терминал и выполните команду:
sudo curl -L "https://github.com/docker/compose/releases/download/2.2.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
Задайте разрешения, чтобы docker-compose
стала исполняемой командой на Ubuntu:
sudo chmod +x /usr/local/bin/docker-compose
Чтобы проверить статус установки, выполните команду:
docker-compose --version
Если установка прошла успешно, в выводе будет указана версия Docker Compose.
Настройка docker-compose.yaml
Файл docker-compose.yaml
используется для конфигурации контейнерной среды. Для демонстрации его работы создадим среду разработки с образом Nginx. Среда будет обслуживать тестовый файл index.html
.
Создайте новый каталог и перейдите в него:
mkdir ~/compose-demo cd ~/compose-demo
Создайте еще один каталог. Он будет корневым для среды Nginx:
mkdir app
Создайте файл index.html
и наполните его демонстрационным контентом. Пример:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Highload Demo Compose</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/kognise/water.css@latest/dist/dark.min.css"> </head> <body> <h1>Hi! It’s a demo page.</h1> <p>We are testing a Nginx container.</p> </body> </html>
Создайте конфигурационный файл docker-compose.yaml
. Скопируйте в него:
version: '3.7' services: web: image: nginx:alpine ports: - "8000:80" volumes: - ./app:/usr/share/nginx/html
Файл начинается с объявления версии конфигурации. В блоке services
настраиваются службы, которые являются частью контейнерной среды. В этом примере служба одна — web
. Она использует образ nginx:alpine
.
Директива ports
настраивает переадресацию портов. Запросы на порт 8000 (локальная машина) будут перенаправляться на порт 80 службы web
в контейнере.
Директива volumes
создает общий том. Контейнер будет иметь доступ к папке app. Сам общий том располагается в каталоге /usr/share/nginx/html
. Он заменит корневой каталог документов Nginx.
В этом примере мы рассматриваем небольшую контейнерную среду. Давайте посмотрим, как указанная конфигурация будет работать на практике.
Запуск
Загрузите нужный образ, создайте контейнер для служб и запустите среду в фоновом режиме командой:
docker-compose up -d
Docker Compose сначала поищет образ в локальной системе. Если его нет, то скачает из Docker Hub.
Чтобы проверить активность среды, выполните в терминале:
docker-compose ps
В выводе отобразится список работающих контейнеров, их состояние, действующая переадресация портов.
Чтобы проверить работоспособность приложения, откройте браузер и перейдите по адресу localhost:8000 (your_server_domain_or_IP:8000
для приложений, запущенных на удаленном сервере). На странице должен отобразиться текст из файла index.html
.
Содержимое файла index.html
можно менять и автоматически обновлять внутри контейнера. Это удобно при разработке. Такая возможность появилась благодаря использованию общего тома, который синхронизирует файлы в папке app
с корневым каталогом документов контейнера.
Основные команды
Эти команды нужны для управления контейнерами и взаимодействия с ними. Список не исчерпывающий — изучим только часто используемые сценарии.
Посмотреть логи:
docker-compose logs
Приостановить работу контейнерной среды без изменения текущего состояния контейнеров:
docker-compose pause
Возобновить работу после паузы:
docker-compose unpause
Остановить выполнение контейнера без удаления связанных с ним данных:
docker-compose stop
Удалить контейнеры, сети и тома, которые связаны с контейнерной средой:
docker-compose down
Удалить образ, из которого собирается среда:
docker image rm name:tag
6. Подробнее о структуре docker-compose.yaml
Выше мы написали очень простой пример файла Docker Compose. Этот раздел — для тех, кто хочет лучше разобраться в его структуре и особенностях.
Элементы верхнего уровня, которые можно использовать в compose.yaml
:
version
— версия формата конфигурационного файла, скоро этот элемент должны исключить;services
— список контейнеров, которые нужно запустить в изолированной среде, это обязательный элемент;networks
— подсети Docker Network, которые объединяют группы контейнеров в локальную сеть, доступную из внешнего мира;volumes
— список томов, которыми будут пользоваться контейнеры, указанные в файле конфигурации;configs
— параметры, позволяющие запускать контейнеры в разных режимах без необходимости собирать их заново;secrets
— чувствительные с точки зрения безопасности параметры, по сути, то же, что иconfigs
, но специального назначения.
Очень подробно спецификация элементов расписана в отдельном репозитории на GitHub. Здесь же давайте познакомимся поближе с тремя часто используемыми элементами — services, networks и volumes.
Services
В мультиконтейнерном приложении сервисы взаимодействуют друг с другом. Как правило, они делятся так, чтобы один обеспечивал одну функцию. Например, API — для обмена данными, веб-сервер — чтобы отдавать статичный сайт, база данных — чтобы хранить данные.
При разработке мультиконтейнерных приложений нужно думать о потенциальном масштабировании. Если пользователей станет больше, то Docker Compose может автоматически использовать дополнительные экземпляры сервиса, перенаправляя на них трафик.
Посмотрим на конкретном примере. Здесь описана конфигурация двух сервисов — для фронтенда и бэкенда:
services: frontend: image: awesome/app build: ./app deploy: mode: replicated replicas: 7 backend: image: awesome/db build: context: backend dockerfile: ../backend.Dockerfile deploy: resources: limits: cpus: '0.60' memory: 60M reservations: cpus: '0.15' memory: 10M
Обратите внимание на настройки mode и replicas
для элемента deploy
у сервиса frontend
. В них мы указываем, что нужно обеспечить до восьми экземпляров сервиса. Его ресурсы будут расходоваться до тех пор, пока не закончатся.
Для сервиса backend
мы указываем другие настройки. Образ собирается перед использованием приложения. В настройке context
содержится относительный путь к папке сервиса. Есть также требования к используемым ресурсам:
- Не более 60% процессора в штатном режиме, до 75% на пиковых нагрузках.
- Не более 60 МБ оперативной памяти и не более 70 МБ на пиковых нагрузках.
Networks
В параметрах элемента Networks
описываются настройки виртуальной сети для совместной работы нескольких контейнеров. В этом примере мы указываем две подсети, одна из которых связывает фронтенд с бэкендом, а другая — фронтенд с внешним миром.
services: frontend: image: awesome/app networks: - front-tier - back-tier backend: image: awesome/db networks: - back-tier networks: front-tier: external: true name: host back-tier:
Volumes
Тома Docker Volumes
используются для хранения данных. В этом примере мы обеспечиваем работу БД, которая расположена в отдельной папке:
services: backend: image: awesome/db volumes: - db-data:/etc/data volumes: db-data:
7. Примеры проектов с Docker Compose
Содержимое файла docker-compose.yaml
зависит от того, какие инструменты используются в проекте. Например, если ваш стек Nginx / Flask / MongoDB, то структура должна быть следующей:
├── docker-compose.yaml ├── flask │ ├── Dockerfile │ ├── requirements.txt │ └── server.py └── nginx └── nginx.conf
Базовый docker-compose
в таком случае будет выглядеть так:
services: web: image: nginx volumes: - ./nginx/nginx.conf:/tmp/nginx.conf environment: - FLASK_SERVER_ADDR=backend:9091 command: /bin/bash -c "envsubst < /tmp/nginx.conf > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" ports: - 80:80 depends_on: - backend backend: build: flask environment: - FLASK_SERVER_PORT=9091 volumes: - ./flask:/src depends_on: - mongo mongo: image: mongo
Файл может выглядеть и сложнее. В качестве примера возьмем стек React, Spring и MySQL.
Структура проекта:
. ├── backend │ ├── Dockerfile │ ... ├── db │ └── password.txt ├── docker-compose.yaml ├── frontend │ ├── ... │ └── Dockerfile └── README.md
Конфигурация Docker Compose:
services: backend: build: backend restart: always secrets: - db-password environment: MYSQL_HOST: db networks: - react-spring - spring-mysql depends_on: db: condition: service_healthy db: # We use a mariadb image which supports both amd64 & arm64 architecture image: mariadb:10.6.4-focal # If you really want to use MySQL, uncomment the following line #image: mysql:8.0.19 environment: - MYSQL_DATABASE=example - MYSQL_ROOT_PASSWORD_FILE=/run/secrets/db-password restart: always healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"] interval: 3s retries: 5 start_period: 30s secrets: - db-password volumes: - db-data:/var/lib/mysql networks: - spring-mysql frontend: build: context: frontend target: development ports: - 3000:3000 volumes: - ./frontend/src:/code/src - /project/node_modules networks: - react-spring depends_on: - backend expose: - 3306 - 33060 volumes: db-data: {} secrets: db-password: file: db/password.txt networks: react-spring: {} spring-mysql: {}
Выглядит устрашающе, но теперь вы должны понимать, что значат все эти элементы и как можно менять конфигурацию в зависимости от своих потребностей.
Еще больше полезной информации — в репозитории Awesome Compose на GitHub. Там вы найдете примеры приложений с несколькими интегрированными службами, одиночные сервисы, а также базовые настройки для разных платформ.
8. Практика: простое приложение на Django/PostgreSQL
Создайте пустую папку проекта. Имя может быть любым. В каталоге должны содержаться только ресурсы для создания image
.
Разместите в каталог проекта файл Dockerfile
. Он определяет содержимое image
. Добавьте в файл следующие строки:
FROM python:3 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 WORKDIR /code COPY requirements.txt /code/ RUN pip install -r requirements.txt COPY . /code/
Создайте файл requirements.txt
в каталоге проекта и добавьте в него зависимости, которые требуются для работы приложения:
Django>=3.0,<4.0 psycopg2>=2.8
Создайте файл docker-compose.yaml
в каталоге приложения. Скопируйте в него следующую конфигурацию:
version: "3.9" services: db: image: postgres volumes: - ./data/db:/var/lib/postgresql/data web: build: . command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/code ports: - "8000:8000" environment: - POSTGRES_NAME=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres depends_on: - db
В файле docker-compose.yaml
определены две службы — db
и web
. Обратите внимание — в конфигурации используется порт 8000. Это решение подходит только для локальной разработки, на продакшене так делать нельзя.
Создайте проект Django. Перейдите в корень каталога приложения и выполните команду:
sudo docker-compose run web django-admin startproject composeexample .
Этой командой вы предписываете django-admin startproject composeexample
выполниться в контейнере с использованием web image
. Поскольку его пока нет, Compose построит web
из текущего каталога, как указано в файле docker-compose.yaml
.
Посмотрите содержимое контейнера после выполнения команды:
ls -l Output: drwxr-xr-x 2 root root composeexample -rw-rw-r-- 1 user user docker-compose.yaml -rw-rw-r-- 1 user user Dockerfile -rwxr-xr-x 1 root root manage.py -rw-rw-r-- 1 user user requirements.txt
Затем подключите базу данных. Откройте и отредактируйте файл composeexample/settings.py
. Найдите строку “DATABASES =”
и замените ее на:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ.get('POSTGRES_NAME'), 'USER': os.environ.get('POSTGRES_USER'), 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), 'HOST': 'db', 'PORT': 5432, } }
Сохраните и закройте файл.
Вернитесь в каталог верхнего уровня проекта и выполните команду:
docker-compose up Output: djangosample_db_1 is up-to-date Creating djangosample_web_1 ... Creating djangosample_web_1 ... done Attaching to djangosample_db_1, djangosample_web_1 db_1 | The files belonging to this database system will be owned by user "postgres". db_1 | This user must also own the server process. db_1 | db_1 | The database cluster will be initialized with locale "en_US.utf8". db_1 | The default database encoding has accordingly been set to "UTF8". db_1 | The default text search configuration will be set to "english". <...> web_1 | July 30, 2020 - 18:35:38 web_1 | Django version 3.0.8, using settings 'composeexample.settings' web_1 | Starting development server at http://0.0.0.0:8000/ web_1 | Quit the server with CONTROL-C.
Приложение должно заработать. Чтобы убедиться в этом, откройте браузер и перейдите по адресу http://localhost:8000.
Посмотрите список запущенных процессов командой:
docker ps
Должны отобразиться две службы — Django и Postgres.
Остановите приложение сочетанием клавиш Ctrl + C или используйте команду:
docker-compose down
У вас получился контейнер с двумя интегрированными службами, который можно улучшать и масштабировать.
Заключение
В этом руководстве раскрыты только основы использования Docker Compose. На практике вам придется часто обращаться к документации, которая очень подробно описывает возможности и особенности применения этого инструмента управления контейнерами.
Чтобы закрепить знания по Docker Compose, посмотрите это тематическое видео:
Сообщить об опечатке
Текст, который будет отправлен нашим редакторам: