Рубріки: Теория

Руководство по 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

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

Вы можете создавать несколько сред окружения на одном хосте, используя название проекта в различных контекстах:

  1. Создать на одном хосте несколько копий одного и того же окружения.
  2. Установить название проекта с номером сборки для исключения конфликта версий на сервере.
  3. Изолировать разные проекты на хосте, которые могут использовать сервисы с одинаковыми названиями.

По умолчанию названием проекта становится имя его корневой директории. Но его можно задать самостоятельно, используя опцию -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:

  1. version — версия формата конфигурационного файла, скоро этот элемент должны исключить;
  2. services — список контейнеров, которые нужно запустить в изолированной среде, это обязательный элемент;
  3. networks — подсети Docker Network, которые объединяют группы контейнеров в локальную сеть, доступную из внешнего мира;
  4. volumes — список томов, которыми будут пользоваться контейнеры, указанные в файле конфигурации;
  5. configs — параметры, позволяющие запускать контейнеры в разных режимах без необходимости собирать их заново;
  6. 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, посмотрите это тематическое видео:

Останні статті

Обучение Power BI – какие онлайн курсы аналитики выбрать

Сегодня мы поговорим о том, как выбрать лучшие курсы Power BI в Украине, особенно для…

13.01.2024

Work.ua назвал самые конкурентные вакансии в IТ за 2023 год

В 2023 году во всех крупнейших регионах конкуренция за вакансию выросла на 5–12%. Не исключением…

08.12.2023

Украинская IT-рекрутерка создала бесплатный трекер поиска работы

Unicorn Hunter/Talent Manager Лина Калиш создала бесплатный трекер поиска работы в Notion, систематизирующий все этапы…

07.12.2023

Mate academy отправит работников в 10-дневный оплачиваемый отпуск

Edtech-стартап Mate academy принял решение отправить своих работников в десятидневный отпуск – с 25 декабря…

07.12.2023

Переписки, фото, история браузера: киевский программист зарабатывал на шпионаже

Служба безопасности Украины задержала в Киеве 46-летнего программиста, который за деньги устанавливал шпионские программы и…

07.12.2023

Как вырасти до сеньйора? Девелопер создал популярную подборку на Github

IT-специалист Джордан Катлер создал и выложил на Github подборку разнообразных ресурсов, которые помогут достичь уровня…

07.12.2023