Настало время рассмотреть стеки в Docker Swarm. Благодаря стекам можно создавать группы сервисов, пописывая всю конфигурацию в compose-файле.
Stack — это “пакет” (группа) из нескольких сервисов, сетей, томов, описанных в одном compose-файле.
1️⃣ Самый простой compose-файл для Docker Swarm Stack
Ниже самый банальный пример compose-файла для создания “пакета” (группы) сервисов web, api. У каждого сервиса по одной реплике задачи/контейнера.
🗃️ stack1.yml
version: "3.8"
services:
web:
image: nginx:latest
ports:
- "8080:80"
networks:
- backend
api:
image: tipoit/py-hostname:1.0
networks:
- backend
networks:
backend:
driver: overlay
Для того, чтобы создать сервисы из файла выше использую команду docker stack deploy -c stack1.yml mystack1. В итоге при выполнении этой команды Swarm создаёт:
- сервис
mystack_web - сервис
mystack_api - сеть
mystack1_backend
Данная команда на вид выполнится довольно быстро, но выполнение всех необходимых задач происходит в фоном режиме.
2️⃣ Просмотр стеков
Когда стек создан можно и проверить что там внутри него. Первым делом выведу список всех стеков в кластере.
docker stack ls
NAME SERVICES
mystack1 2
3️⃣ Просмотр сервисов стека
Для того чтобы получить список сервисов определённого стека используется команда docker stack services.
docker stack services mystack1
ID NAME MODE REPLICAS IMAGE PORTS
j3n3r4fv6itm mystack1_api replicated 1/1 tipoit/py-hostname:1.0
iz5pz1t2p4uz mystack1_web replicated 1/1 nginx:latest *:8080->80/tcp
4️⃣ Просмотр задач/контейнеров стека
Да для этого можно использовать и обычную команду docker service ps, но можно заменить её и на docker stack ps и получить вообще все задачи всех сервисов в стеке.
docker stack ps mystack1
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
sutyb5hy2irr mystack1_api.1 tipoit/py-hostname:1.0 c-stream-9-vm4 Running Running 39 seconds ago
dnd7kdyct9qa mystack1_web.1 nginx:latest c-stream-9-vm8 Running Running 37 seconds ago
5️⃣ Как связаны stack и service
Как уже стало понятно из текста выше стек состоит из сервисов, стало быть сервисы из одного стека как-то связанны с ним. Во-первых, все сервисы связанны между собой, так как в примере выше используется только одна сеть mystack1_backend, которая принадлежит стеку mystack1.
Каждый сервис стека после создания имеет следующую структуру имени:
Также можно использовать docker service inspect для того чтобы узнать к какому стеку принадлежит сервис.
docker service inspect mystack1_web --format ''
{"com.docker.stack.image":"nginx:latest","com.docker.stack.namespace":"mystack1"}
docker service ls --filter label=com.docker.stack.namespace=mystack1
ID NAME MODE REPLICAS IMAGE PORTS
krlkybxksuvk mystack1_api replicated 1/1 tipoit/py-hostname:1.0
mkdr6mt164tx mystack1_web replicated 1/1 nginx:latest *:8080->80/tcp
swarm-stack-service-linking.svg
6️⃣ Удаление стека
Как и в случае с удалением других компонентов кластера используется опция rm, т.е. команда удаления стека выглядит так: docker stack rm. Причём тут не надо задавать никакого подтверждения после выполнения этой команды весь стек сервисов будет удалён без единого запроса подтверждения на это, будьте осторожны.
docker stack rm mystack1
Удаление стека также проходит в фоновом режиме. Так что пока стек полностью не удалится не создавайте новый с таким же именем, либо можно использовать --detach=false.
6️⃣ Build не работает
При использовании docker compose в файле можно использовать параметр build, для того чтобы собрать образ для контейнера при создании контейнеров. Но в файле конфигурации для стека build использовать нельзя. При попытке это сделать вы просто получите ошибку services.api.build Additional property build is not allowed выполняя команду docker stack build.
Причина на самом деле проста. Swarm — это кластер. Он может запускать сервисы на любом узле кластера, а build происходит только локально. Значит, собирать образ внутри stack нельзя.
Дело в том, что Docker не может гарантировать:
- что образ соберётся одинаково на каждой ноде;
- что нода, на которую Swarm поставит сервис, имеет исходники;
- что билд-окружение одинаковое.
Поэтому правильнее всего будет сделать так:
- Собираешь образ локально или в CI (docker build)
- Загрузить его в репозиторий (docker push)
- В файле stack.yml указать образ с репозитория
Помимо build в файле конфигурации стека нельзя указывать следующее:
- depends_on
- container_name
- restart
- links


Комментарии