[Перевод] Docker Compose: упрощение работы с использованием Makefile

Каждые несколько лет в индустрии разработки ПО происходит смена парадигмы. Одним из таких явлений можно признать рост интереса к концепции микросервисов. Хотя микросервисы — это технология не самая новая, лишь в последнее время её популярность буквально взлетела до небес.

Большие монолитные сервисы в наши дни заменяют независимыми автономными микросервисами. Микросервис можно рассматривать как приложение, которое служит единственной и очень специфической цели. Например — это может быть реляционная СУБД, Express-приложение, Solr-сервис.

xj7xqrze4d6ijidic1zuonqbr1c.jpeg

В наши дни сложно представить себе разработку новой программной системы без применения микросервисов. А эта ситуация, в свою очередь, ведёт нас к платформе Docker.

Docker


Платформа Docker, в деле разработки и развёртывания микросервисов, стала практически индустриальным стандартом. На сайте проекта можно узнать о том, что Docker — это единственная независимая платформа контейнеризации, которая позволяет организациям без особых усилий создавать любые приложения, а также распространять и запускать их в любых средах — от гибридных облаков, до пограничных систем.

Docker Compose


Технология Docker Compose предназначена для конфигурирования многоконтейнерных приложений. В Docker Compose-проект может входить столько контейнеров Docker, сколько нужно создателю этого проекта.

При работе с Docker Compose для настройки сервисов приложения и организации их взаимодействия друг с другом используется YAML-файл. Docker Compose, таким образом, это инструмент для описания и запуска многоконтейнерных приложений Docker.

49cb5a9bf3288a6cd933c6210f8a56bf.png


Два контейнера, работающие на хост-системе

GNU Make


Программа make, по существу, представляет собой инструмент для автоматизации сборки программ и библиотек из исходного кода. В целом, можно говорить о том, что make применима к любому процессу, который включает в себя выполнение произвольных команд для преобразования неких исходных материалов к некоему результирующему виду, к некоей цели. В нашем случае команды docker-compose будут преобразовываться в абстрактные цели (Phony targets).

Для того чтобы сообщить программе 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.


c92808916bcd3d861c25a47c22cc1694.png


Справка по доступным командам

  • make build — сборка образа из Dockerfile. В нашем примере мы использовали существующие образы timescale и ping. Но образ api мы хотим собрать локально. Именно это и будет сделано после выполнения данной команды.


8a523f8fca803a9b2c21411d7e3ad037.png


Сборка контейнера Docker

  • make start — запуск всех контейнеров. Для запуска лишь одного контейнера можно воспользоваться командой вида make start c=timescale.


087f725597d994d7929e50da56dd2d4d.png


Запуск контейнера timescale

1eea134e39cf2c8d58dac881c143c135.png


Запуск контейнера ping

  • make login-timescale — вход в bash-сессию контейнера timescale.


b8763a66cdb78760244cb41ea6c26c6e.png


Запуск bash в контейнере timescale

  • make db-shell — вход в psql в контейнере timescale для выполнения SQL-запросов к базе данных.


ac66693e81e9adefdbf14b2541ba176d.png


Запуск psql в контейнере timescaledb

  • make stop — остановка контейнеров.


bf90f8cb006ba2ec136a4bdf6b956de3.png


Остановка контейнера timescale

  • make down — остановка и удаление контейнеров. Для удаления конкретного контейнера можно использовать эту команду с указанием нужного контейнера. Например — make down c=timescale или make down c=api.


779edefd85df7dcedec4ead9b0bae09f.png


Остановка и удаление всех контейнеров

Итоги


Несмотря на то, что система 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, это упорядочивает совместную работу и снижает количество ошибок.


P.S. В нашем маркетплейсе имеется образ Docker, который устанавливается в один клик. Вы можете проверить работу контейнеров на VPS. Всем новым клиентам бесплатно предоставляются 3 дня для тестирования.

Уважаемые читатели! Как вы автоматизируете работу с Docker Compose?

1ba550d25e8846ce8805de564da6aa63.png

© Habrahabr.ru