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
Заключение
Docker Compose — инструмент для запуска и управления мультиконтейнерными приложениями. Он помогает создать изолированную среду (песочницу), в которой содержатся все необходимые зависимости.
Конфигурация такого приложения описывается в файле YAML. Запустить приложение, ранее собранное в контейнер, можно одной командой.
Docker управляет отдельными сервисами, из которых состоит приложение.
Docker Compose управляет несколькими контейнерами, которые входят в состав приложения. Возможности те же, что и у Docker. Но можно выстраивать более комплексные системы взаимодействия.
Вы можете создавать несколько сред окружения на одном хосте, используя название проекта в различных контекстах:
По умолчанию названием проекта становится имя его корневой директории. Но его можно задать самостоятельно, используя опцию -p или переменную окружения COMPOSE_PROJECT_NAME
.
Docker Compose по умолчанию защищает тома, которые используются сервисами. Если от предыдущего запуска остались тома, то при выполнении команды docker-compose up
данные из них копируются в новые тома.
Compose кэширует конфигурацию, которая была использована для создания контейнера. Если перезапустить контейнер без изменений, то будут использованы существующие файлы. Такое повторное использование обеспечивает быстрое внесение изменений в проект.
Compose поддерживает переменные в файле docker-compose
. Вы можете использовать их для настройки конфигурации под разные среды и/или пользователей. Также можно создать несколько файлов и расширять их с помощью поля extends
в docker-compose
.
Запуск и взаимодействие с приложением в изолированной среде — важная часть разработки. Compose помогает создать необходимое окружение и взаимодействовать с ним через интерфейс командной строки.
Вы описываете все зависимости службы в файле docker-compose
— базы данных, веб-службы API, очереди, кеши. Создать и запустить один или несколько контейнеров можно одной командой — docker-compose up
.
Такой подход помогает значительно ускорить процесс разработки. Не нужны многостраничные инструкции, вся конфигурация укладывается в один небольшой файл.
Для непрерывного проведения автоматизированных тестов нужна изолированная среда. Docker Compose обеспечивает удобный процесс создания и удаления систем для тестирования. Все действия можно уложить в три простые команды:
docker-compose up -d ./run_tests docker-compose down
В этом примере вы запускаете приложение, выполняете необходимые тесты и останавливаете выполнение контейнера.
Традиционно Compose больше используется для разработки и тестирования. Но с каждым новым релизом в нем появляется больше инструментов для деплоя.
На 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
используется для конфигурации контейнерной среды. Для демонстрации его работы создадим среду разработки с образом 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
Выше мы написали очень простой пример файла Docker Compose. Этот раздел — для тех, кто хочет лучше разобраться в его структуре и особенностях.
Элементы верхнего уровня, которые можно использовать в compose.yaml
:
version
— версия формата конфигурационного файла, скоро этот элемент должны исключить;services
— список контейнеров, которые нужно запустить в изолированной среде, это обязательный элемент;networks
— подсети Docker Network, которые объединяют группы контейнеров в локальную сеть, доступную из внешнего мира;volumes
— список томов, которыми будут пользоваться контейнеры, указанные в файле конфигурации;configs
— параметры, позволяющие запускать контейнеры в разных режимах без необходимости собирать их заново;secrets
— чувствительные с точки зрения безопасности параметры, по сути, то же, что и configs
, но специального назначения.Очень подробно спецификация элементов расписана в отдельном репозитории на GitHub. Здесь же давайте познакомимся поближе с тремя часто используемыми элементами — services, networks и volumes.
В мультиконтейнерном приложении сервисы взаимодействуют друг с другом. Как правило, они делятся так, чтобы один обеспечивал одну функцию. Например, 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
содержится относительный путь к папке сервиса. Есть также требования к используемым ресурсам:
В параметрах элемента 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:
Тома Docker Volumes
используются для хранения данных. В этом примере мы обеспечиваем работу БД, которая расположена в отдельной папке:
services: backend: image: awesome/db volumes: - db-data:/etc/data volumes: db-data:
Содержимое файла 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. Там вы найдете примеры приложений с несколькими интегрированными службами, одиночные сервисы, а также базовые настройки для разных платформ.
Создайте пустую папку проекта. Имя может быть любым. В каталоге должны содержаться только ресурсы для создания 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, посмотрите это тематическое видео:
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…