Docker Swarm — режим кластеризации, встроенный в Docker Engine. Он не требует отдельного control plane, не устанавливает операторов и не занимает гигабайты памяти. Достаточно нескольких хостов с Docker, чтобы получить реплики сервисов, overlay-сети, секреты и rolling update. В 2026 году Swarm находится в режиме поддержки: новые крупные функции не появляются, но исправления безопасности и совместимость с текущими версиями Engine сохраняются. Для небольшого кластера это осознанный компромисс между простотой и возможностями Kubernetes.
Когда Swarm уместен
Swarm хорошо ложится на инфраструктуру из трёх, пяти или семи узлов, где нужны несколько реплик веб-приложения, балансировка и предсказуемое обновление. Он не пытается заменить облачную платформу и не требует изучать десятки объектов API.
- Небольшой кластер под внутренние сервисы и сайты.
- Команда уже использует Docker и compose-файлы.
- Нужны секреты, overlay-сеть и откат версии без внешних инструментов.
- Нет ресурсов на сопровождение Kubernetes и его обвязки.
Ограничения тоже важны: нет горизонтального автоскейлинга, ограниченная работа с состоянием, меньше готовых интеграций и наблюдаемости. Если планируется несколько команд и сложные политики доступа, лучше сразу смотреть в сторону Kubernetes. Отдельно продумайте хранение данных: Swarm не управляет состоянием, поэтому база в контейнере требует внешнего тома и собственной стратегии резервного копирования.
Инициализация кластера
Первый узел становится менеджером. Укажите адрес, который видят остальные машины, иначе присоединение пройдёт, но служебный трафик пойдёт не туда. Для отказоустойчивости нужно три менеджера: при двух потеря одного ломает кворум.
docker swarm init --advertise-addr 10.0.0.10
docker node ls
docker swarm join-token worker
docker info --format '{{.Swarm.LocalNodeState}}'
Откройте порты 2377/tcp для управления, 7946/tcp и 7946/udp для обмена между узлами, 4789/udp для overlay-трафика. Токены присоединения дают полный доступ к кластеру, поэтому не храните их в открытых заметках и периодически выполняйте docker swarm join-token --rotate worker.
Сервисы и реплики
Сервис описывает желаемое состояние: образ, число задач, порты и ограничения размещения. Планировщик сам выбирает узлы и перезапускает упавшие задачи.
docker service create --name web --replicas 3 \
--publish published=80,target=8080 \
--constraint 'node.role==worker' \
nginx:alpine
docker service ls
docker service ps web
docker service scale web=5
Публикация в режиме ingress работает через routing mesh: порт открыт на каждом узле, и запрос может попасть на любую реплику. Режим host привязывает порт к конкретному узлу и подходит для сервисов, которым нужен прямой доступ к сети хоста. Ограничения node.labels и node.role помогают разнести нагрузку, но не заменяют честное резервирование ресурсов. Для предсказуемости задавайте лимиты CPU и памяти: без них планировщик может поставить слишком много задач на один узел.
Стек из compose-файла
Стек разворачивает набор сервисов одной командой. Формат близок к compose, но секция deploy обязательна для реплик и политики обновления, а build игнорируется: образы должны быть собраны заранее и доступны всем узлам.
services:
api:
image: registry.example.com/api:1.4
ports:
- "8080:8080"
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
restart_policy:
condition: on-failure
networks:
default:
driver: overlay
Разворачивание выполняет docker stack deploy -c compose.yaml app. Имя стека становится префиксом сервисов и сетей, поэтому обращайтесь к задачам как app_api. Ключ container_name в стеке не работает, а тома типа bind должны существовать на каждом узле.
Обновление и откат
Rolling update идёт задача за задачей. Порядок start-first сначала поднимает новую реплику и только потом гасит старую, поэтому требует запаса ресурсов. Если healthcheck не проходит, обновление останавливается, и сервис можно вернуть к предыдущей версии.
docker service update --image registry.example.com/api:1.5 \
--update-order start-first --update-delay 10s app_api
docker service rollback app_api
docker node update --availability drain node2
docker service inspect --pretty app_api
Перед плановыми работами узел переводят в drain: задачи переезжают на другие машины, новые не назначаются. После обслуживания верните active. Параметры --update-failure-action и --update-max-failure-ratio задают поведение при массовых сбоях.
Секреты и сеть
Секреты монтируются в контейнер как файлы в /run/secrets и не попадают в переменные окружения по умолчанию. Это снижает риск утечки через дамп процесса или логи.
printf 'strong-password' | docker secret create db_password -
docker service create --name db --secret db_password postgres:17-alpine
docker network create --driver overlay --opt encrypted backend
docker service inspect --format '{{json .Spec.TaskTemplate.Networks}}' web
Шифрование overlay-сети включается на уровне сети и защищает трафик между узлами. Локальные тома существуют только на одном хосте, поэтому для базы данных и файлов нужен общий NFS или другой сетевой ресурс. Секреты не предназначены для больших файлов, для конфигураций используйте docker config.
Диагностика
Если задача не запускается, смотрите её историю и причину отказа планировщика. Короткий вывод docker service ps обрезает сообщения, поэтому добавляйте --no-trunc.
docker service ps --no-trunc app_api
docker node inspect node1 --pretty
docker events --filter type=service --since 30m
docker service logs -f app_api
Типичные причины: no suitable node из-за меток или нехватки ресурсов, pull access denied к приватному реестру, занятый порт в режиме host и падающий healthcheck. Если менеджеры теряют кворум, кластер перестаёт принимать изменения; проверьте docker node ls и состояние Raft в docker info.
Резервная копия состояния
Состояние Swarm хранится в каталоге /var/lib/docker/swarm на менеджерах. Копию снимают при остановленном Docker, иначе файлы будут несогласованными.
sudo systemctl stop docker
sudo tar czf /backup/swarm-$(date +%F).tar.gz -C /var/lib/docker swarm
sudo systemctl start docker
docker node ls
Восстанавливать архив нужно на менеджере с остановленным Docker: распакуйте каталог, запустите Docker и выполните docker swarm init --force-new-cluster. Делайте это по согласованной процедуре, а не на работающем кластере. Держите копии на отдельном хосте и проверяйте их до того, как они понадобятся.
Итог
Docker Swarm даёт кластер контейнеров без Kubernetes: несколько команд, понятные сервисы, overlay-сети и откат. Он подходит для небольшой инфраструктуры, где важнее простота, чем расширяемость. Проверьте кворум, порты и резервное копирование состояния, и решение будет предсказуемым в эксплуатации.