Skip to content

Docker Compose

Docker Compose — це технологія, яка дозволяє локально запускати багатоконтейнерні додатки, тобто одночасно один або більше контейнерів. Створення Docker Compose є типовою задачею для DevOps-інженера.

docker-compose — це плагін до Docker, а також це файл з конкретно визначеною нотацією. Колись цей плагін був окремим додатком, але компанія Docker купила його та інтегрувала з рештою системи. docker-compose дозволяє визначати контейнери, які треба запустити, залежності між ними, мережі тощо.

docker-compose можна вважати твоїм першим оркестратором контейнерів. Оркестратор — це додаткове програмне забезпечення, яке допомагає керувати контейнерами, коли їх стає багато, або налаштувати якусь нетипову поведінку.

Структура docker-compose

docker-compose — це YML-файл. Нотація такого файлу досить проста і дещо схожа на JSON, але без дужок, наприклад: docker-compose.yml

version: '3'
networks:
services:
volumes:

У цьому файлі спочатку пишемо поле, потім двокрапку, потім значення поля. У прикладі можна побачити такі поля:

  • version — це версія плагіну docker-compose;
  • networks — це необовʼязкове поле, що описує Docker-мережі;
  • services — це опис та конфігурація того, який контейнер треба запустити і які конфігурації задати;
  • volumes — це volumes, які можна під'єднати у секції services.

Додамо мережу

Тепер зробимо так, щоб з docker-compose створювалась Docker-мережа, яку будуть використовувати контейнери:

networks:
db-data-net:
    driver: bridge

Під секцією networks додай табуляцію і напиши назву мережі. Обов'язково постав двокрапку, щоб не порушити синтаксис. Нижче напиши тип драйвера мережі.

💡 bridge — це тип мережі, яку Docker використовує за замовчуванням. Контейнери, які підключені до мережі такого типу, отримають IP-адресу, виділену з загального IP-пулу цієї мережі. Контейнери, які підключені до одної bridge-мережі, можуть комунікувати між собою, використовуючи внутрішню IP-адресу або назву контейнера. 💡 Ми зазделегідь можемо не знати яку конкретно ІР отримає контейнер тому треба взаємодію додатків з різних контейнерів організовувати по доменним іменам (імʼя контейнеру буде доменним іменем)

Додамо volume

Для початку визначимо наш volume у відповідній секції:

volumes:
 db-data:

У volumes є різні типи драйверів, ми будемо використовувати тип драйвера за замовчуванням — local, який дозволяє створювати volumes на машині хоста контейнера. Щоб використати тип драйвера за замовчуванням, не потрібно вказувати нічого додатково.

Додамо базу даних

Додамо базу даних до services:

 mysql:
   image: my-sql:1.2
   build:
     context: .
     dockerfile: Dockerfile.mysql
   container_name: my-sql
   ports:
     - "3306:3306"
   volumes:
     - db-data:/var/lib/mysql
   environment:
     - MYSQL_ROOT_PASSWORD=1234
     - MYSQL_DATABASE=app_db
     - MYSQL_USER=app_user
     - MYSQL_PASSWORD=1234
   networks:
     - db-data-net

Тут: - my-sql:1.2 — це назва Image, який треба завантажити з Docker Hub або знайти локально. - build — це інструкції, які виконаються, якщо Image не знаходиться локально. Іншими словами, ми описуємо команду, задаємо контекст і шлях до файлу Dockerfile відносно docker-compose. - volumes - вказуємо драйвер та шлях куди мотувати в системі - ports - маппінг портів - environment - визначаємо змінні середовища. - networks - задаємо яку мережу використовуватимемо з загального розділу networks

Додамо Python-додаток

Для нашого додатка задамо:

  1. Image, а якщо його немає, тоді build-параметри.
  2. Мепінги портів.
  3. Змінну середовища, яку ми визначили ще в Dockerfile для Python-додатку.
  4. Мережу.
  5. Параметр depends_on, який вказує, що docker-compose спочатку ініціює запуск бази даних, але не очікуватиме на її повне завершення запуску, тому ще додамо політику restart.
 pythonapp:
   image: app:1.2
   build:
     context: .
     dockerfile: Dockerfile.app
   ports:
     - "8080:8080"
   environment:
     - APP_ENV=Development
   networks:
     - db-data-net
   depends_on:
     - mysql
   restart: unless-stopped

Також модифікуємо connection string у додатку:

mysql+mysqlconnector://app_user:1234@172.17.0.2/app_db
У нас тут прописана IP контейнера, але це не дуже зручно з двох причин: 1. IP може змінитись. 2. Ми запускаємо два контейнери одразу. Ми використаємо назву контейнера для бази даних:
mysql+mysqlconnector://app_user:1234@my-sql/app_db

Час це все запустити, але спочатку очистимо увесь кеш:

docker system prune -a

У терміналі у теці з docker-compose і виконай наступну команду:

docker-compose up -d 

Параметр -d еквівалентний --detach і означає, що вивід логів буде прихований. Якщо не вказувати цей параметр, то логи обох контейнерів ми побачимо в консолі.

Cтатус контейнерів:

docker compose ps
Логи контейнерів:
docker compose logs
Щоб зупинити всі контейнери:
docker-compose down
Можна перезапускати в одному рядку:
docker-compose down; docker-compose up -d