Кожні кілька років у промисловості розробки ПЗ відбувається зміна парадигми. Одним із таких явищ можна визнати зростання інтересу до концепції мікросервісів. Хоча мікросервіси - це технологія не найновіша, лише останнім часом її популярність буквально злетіла до небес.
Великі монолітні послуги в наші дні замінюють незалежними автономними мікросервісами. Мікросервіс можна розглядати як додаток, який є єдиною і дуже специфічною метою. Наприклад, це може бути реляційна СУБД, Express-додаток, Solr-сервіс.
У наші дні важко уявити розробку нової програмної системи без застосування мікросервісів. А ця ситуація, у свою чергу, веде нас до платформи Docker.
Docker
Платформа
Docker Compose
Технологія
При роботі з Docker Compose для налаштування сервісів програми та організації їхньої взаємодії один з одним використовується YAML-файл. Docker Compose, таким чином, це інструмент для опису та запуску багатоконтейнерних програм Docker.
Два контейнери, що працюють на хост-системі
GNU Make
Програма make
, по суті, є інструментом для автоматизації складання програм і бібліотек з вихідного коду. Загалом можна говорити про те, що make
застосовна до будь-якого процесу, який включає виконання довільних команд для перетворення деяких вихідних матеріалів до якогось результуючого виду, до якоїсь мети. У нашому випадку команди docker-compose
будуть перетворюватися на абстрактні цілі (
Для того, щоб повідомити програму make
про те, чого ми від неї хочемо, нам знадобиться файл Makefile
.
У нашому Makefile
будуть утримуватися звичайні команди docker
и docker-compose
, які призначені для вирішення безлічі завдань. А саме, йдеться про складання контейнера, про його запуск, зупинку, перезапуск, про організацію входу користувача в контейнер, про роботу з логами контейнера та про вирішення інших подібних завдань.
Типові варіанти використання Docker Compose
Уявімо собі звичайне веб-додаток, в якому є такі компоненти:
- База даних TimescaleDB (Postgres).
- Express.js-додаток.
- Ping (просто контейнер, що нічого особливого не робить).
Цьому додатку знадобиться 3 контейнери Docker та файл docker-compose
, що містить інструкції з управління цими контейнерами Кожен з контейнерів матиме різні точки взаємодії. Наприклад, із контейнером timescale
можна буде працювати приблизно так, як працюють із базами даних. А саме він дозволяє виконувати наступні дії:
- Вхід до оболонки Postgres.
- Імпорт та експорт таблиць.
- Створення
pg_dump
таблиці чи бази даних.
Контейнер Express.js-додатки, expressjs
, може мати такі можливості:
- Видача свіжих даних із системного журналу.
- Вхід у оболонку до виконання деяких команд.
Взаємодія з контейнерами
Після того, як ми налаштували зв'язок між контейнерами із використанням Docker Compose, настав час налагодження взаємодії з цими контейнерами. В рамках системи Docker Compose є команда docker-compose
, що підтримує опцію -f
яка дозволяє передавати системі файл docker-compose.yml
.
Використовуючи можливості цієї опції, можна обмежити взаємодію із системою лише тими контейнерами, які згадані у файлі docker-compose.yml
.
Погляньмо на те, як виглядають взаємодії з контейнерами при використанні команд docker-compose
. Якщо уявити, що нам потрібно увійти в оболонку psql
, то відповідні команди можуть виглядати так:
docker-compose -f docker-compose.yml exec timescale psql -Upostgres
Та ж команда, для виконання якої використовується не docker-compose
, а docker
, може виглядати так:
docker exec -it edp_timescale_1 psql -Upostgres
Зверніть увагу на те, що в подібних випадках завжди краще використовувати не команду docker
, а команду docker-compose
, так як це дозволяє позбутися необхідності пам'ятати імена контейнерів.
Обидві наведені вище команди не такі вже й складні. Але якби ми скористалися «оберткою» у вигляді Makefile
, яка давала б нам інтерфейс у вигляді простих команд і сама б викликала подібні довгі команди, то тих же результатів можна було б досягти так:
make db-shell
Цілком очевидно те, що використання Makefile
значно полегшує роботу з контейнерами!
Робочий приклад
На основі вищезазначеної схеми проекту створимо наступний файл docker-compose.yml
:
version: '3.3'
services:
api:
build: .
image: mywebimage:0.0.1
ports:
- 8080:8080
volumes:
- /app/node_modules/
depends_on:
- timescale
command: npm run dev
networks:
- webappnetwork
timescale:
image: timescale/timescaledb-postgis:latest-pg11
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
command: ["postgres", "-c", "log_statement=all", "-c", "log_destination=stderr"]
volumes:
- ./create_schema.sql:/docker-entrypoint-initdb.d/create_schema.sql
networks:
- webappnetwork
ping:
image: willfarrell/ping
environment:
HOSTNAME: "localhost"
TIMEOUT: 300
networks:
webappnetwork:
driver: bridge
Для керування конфігурацією Docker Compose та для взаємодії з контейнерами, які вона описує, створимо наступний файл Makefile
:
THIS_FILE := $(lastword $(MAKEFILE_LIST))
.PHONY: help build up start down destroy stop restart logs logs-api ps login-timescale login-api db-shell
help:
make -pRrq -f $(THIS_FILE) : 2>/dev/null | awk -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | sort | egrep -v -e '^[^[:alnum:]]' -e '^$@$$'
build:
docker-compose -f docker-compose.yml build $(c)
up:
docker-compose -f docker-compose.yml up -d $(c)
start:
docker-compose -f docker-compose.yml start $(c)
down:
docker-compose -f docker-compose.yml down $(c)
destroy:
docker-compose -f docker-compose.yml down -v $(c)
stop:
docker-compose -f docker-compose.yml stop $(c)
restart:
docker-compose -f docker-compose.yml stop $(c)
docker-compose -f docker-compose.yml up -d $(c)
logs:
docker-compose -f docker-compose.yml logs --tail=100 -f $(c)
logs-api:
docker-compose -f docker-compose.yml logs --tail=100 -f api
ps:
docker-compose -f docker-compose.yml ps
login-timescale:
docker-compose -f docker-compose.yml exec timescale /bin/bash
login-api:
docker-compose -f docker-compose.yml exec api /bin/bash
db-shell:
docker-compose -f docker-compose.yml exec timescale psql -Upostgres
Більшість описаних тут команд застосовуються до всіх контейнерів, але використання опції c=
дозволяє обмежити область дії команди одного контейнера.
Після того, як Makefile
готовий, користуватися ним можна так:
make help
- Видача переліку всіх команд, доступних дляmake
.
Довідка щодо доступних команд
make build
- Складання образу зDockerfile
. У прикладі ми використовували існуючі образиtimescale
иping
. Але образapi
ми хочемо зібрати локально. Саме це і буде зроблено після виконання цієї команди.
Складання контейнера Docker
make start
- Запуск усіх контейнерів. Для запуску лише одного контейнера можна скористатися командою видуmake start c=timescale
.
Запуск контейнера timescale
Запуск контейнера ping
make login-timescale
- Вхід у bash-сесію контейнераtimescale
.
Запуск bash у контейнері timescale
make db-shell
- Вхід доpsql
у контейнеріtimescale
для виконання SQL-запитів до бази даних.
Запуск psql у контейнері timescaledb
make stop
- Зупинка контейнерів.
Зупинка контейнера Timescale
make down
- Зупинка та видалення контейнерів. Для видалення конкретного контейнера можна використовувати цю команду із зазначенням потрібного контейнера. Наприклад -make down c=timescale
абоmake down c=api
.
Зупинка та видалення всіх контейнерів
Підсумки
Незважаючи на те, що система Docker Compose дає в наше розпорядження великий набір команд, призначених для керування контейнерами, іноді ці команди стають довгими, тому їх буває складно запам'ятати.
Методика використання Makefile
допомогла нам налагодити швидку та просту взаємодію з контейнерами з файлу docker-compose.yml
. А саме, йдеться про наступне:
- Розробник взаємодіє лише з контейнерами проекту, описаними в
docker-compose.yml
роботі не заважають інші запущені контейнери. - У тому випадку, якщо якусь команду забуто, можна виконати команду
make help
та отримати довідку щодо доступних команд. - Не потрібно запам'ятовувати довгі списки аргументів для виконання таких дій, як отримання свіжих записів журналу або вхід до системи. Наприклад, команда виду
docker-compose -f docker-compose.yml exec timescale psql -Upostgres
перетворюється вmake db-shell
. - Файл
Makefile
можна, зі зростанням проекту, гнучко під нього підлаштовувати. Наприклад, до нього нескладно додати команду для створення резервної копії бази даних або для виконання будь-якої іншої дії. - Якщо велика команда розробників користується одним і тим же
Makefile
, це впорядковує спільну роботу та знижує кількість помилок.
PS У нашому
Шановні читачі! Як автоматизувати роботу з Docker Compose?
Джерело: habr.com