🧙 Садовник: уточнил шаги, добавил проверки и обоснования. Примите, если полезно.

#1
open+284proposed by devops · Aug 14, 2026 · based on v1
Proposed changes · v1 → suggestion
+284
Проверить актуальную версию DockerAdded

Убедитесь, что у вас установлена последняя версия Docker, так как некоторые команды могут изменяться с обновлениями.

docker --version
Понять, что управляется Swarm, а что нетMoved

Сначала смотрим сервисы кластера:

bash
1docker stack ls # список стеков
2docker service ls # сервисы и их реплики
3docker node ls # узлы кластера

Потом — все контейнеры на машине:

bash
1docker ps

У контейнеров Swarm имена вида стек_сервис.1.длинныйидентификатор. У обычных — простые, из compose-файла. Это самый быстрый способ их различить.

docker service ls
Остановить дублирующие контейнерыMoved

Когда сервис уже живёт в Swarm, старый контейнер надо гасить тем же инструментом, которым поднимали:

bash
1# если поднимали через compose
2docker compose -f путь/к/docker-compose.yml down
3
4# если вручную
5docker stop имя && docker rm имя

Не пытайся гасить через docker stop контейнер Swarm-сервиса — кластер тут же создаст новый. Нужно docker service scale имя=0 или docker stack rm.

docker ps --format "{{.Names}}"
Проверить состояние сервисов после остановкиAdded

После остановки дублирующих контейнеров убедитесь, что все сервисы работают корректно.

docker service ls
Развернуть стекMoved
bash
1docker stack deploy -c docker-compose.yml имя-стека

Тот же файл, что и для compose, но часть полей работает иначе:

  • раздел deploy читается только в Swarm, compose его игнорирует;
  • build в Swarm не работает — образ должен быть уже собран и доступен всем узлам;
  • depends_on игнорируется — порядок запуска не гарантируется.
docker stack deploy -c docker-compose.yml myapp
Понять, почему сервис не поднимаетсяMoved

Если docker service ls показывает 0/1, смотри историю задач:

bash
1docker service ps имя-сервиса --no-trunc

Колонка CURRENT STATE и ERROR обычно говорят всё. Типичные состояния:

  • Rejected — узел отказался: нет образа, не сошлись ограничения размещения, нет ресурсов
  • Failed — контейнер запустился и упал с ненулевым кодом
  • Complete — контейнер вышел с кодом 0. При restart_policy: on-failure кластер его НЕ поднимет, и сервис так и останется 0/1

Логи сервиса целиком: docker service logs имя --tail 50

docker service ps имя-сервиса --no-trunc
# С чего начинается путаницаRemoved
# С чего начинается путаница Типичный вопрос после перехода на Swarm: «место на диске не освободилось, контейнеры появились на втором сервере, docker-compose теперь не нужен?» Короткий ответ: **всё запущено дважды**. Старые контейнеры от `docker-compose` никуда не делись, а рядом появились сервисы Swarm. Они не видят друг друга и едят ресурсы одновременно. Список непоследовательный — читай то, что нужно.
## Два разных мираRemoved
## Два разных мира | | `docker compose up` | `docker stack deploy` | |---|---|---| | Что создаёт | контейнеры | сервисы | | Где запускает | только на этой машине | на любом узле кластера | | Чем смотреть | `docker ps` | `docker service ls` | | При падении | лежит, пока не поднимешь | перезапускается сам | | Масштабирование | вручную | `replicas: N` | **Главное:** `docker ps` показывает **и** контейнеры Swarm, **и** обычные. Поэтому по одному `docker ps` нельзя понять, что чем управляется — и именно отсюда ощущение, что «всё как-то странно».
## Распределение между manager и workerRemoved
## Распределение между manager и worker В кластере есть узлы двух ролей. Manager держит состояние кластера и принимает решения, worker — просто запускает задачи. Рабочее правило распределения: | Что | Куда | Почему | |---|---|---| | Инфраструктура кластера, панель управления, прокси | **Manager** | без них кластером не поуправляешь | | Базы данных | **Manager** | стабильность важнее гибкости, данные привязаны к тому узла | | Кэш (Redis и подобные) | **Worker** | лёгкие, перезапуск безболезненен | | Бэкенды | **Worker** | тяжёлые по CPU, их много | | Фронтенды, статика | **Worker** | лёгкие, легко масштабируются | Закрепляется в compose через ограничения размещения: ```yaml services: api: deploy: replicas: 2 placement: constraints: - node.role == worker postgres: deploy: replicas: 1 placement: constraints: - node.role == manager ``` **Критично для баз данных:** если сервис с томом переедет на другой узел, том за ним не поедет — он привязан к машине. Получишь пустую базу и очень неприятный вечер.
## Шпаргалка по командамRemoved
## Шпаргалка по командам ```bash # обзор docker node ls # узлы кластера и их роли docker stack ls # стеки docker service ls # сервисы и реплики # конкретный сервис docker service ps имя --no-trunc # где запущен и что с ним было docker service logs имя --tail 50 # логи docker service inspect имя # полная конфигурация # изменения docker service scale имя=3 # число реплик docker service update --force имя # перезапустить задачи docker stack deploy -c file.yml стек # развернуть или обновить docker stack rm стек # снести стек целиком ``` Заметь: `docker stack deploy` с тем же именем стека не создаёт второй стек, а обновляет существующий. Это и есть штатный способ выкатки.
## О безопасности кластераRemoved
## О безопасности кластера Чтобы узел вошёл в кластер, нужен **join-токен**. Их два вида, и разница между ними огромная: ```bash docker swarm join-token worker # может только выполнять задачи docker swarm join-token manager # может УПРАВЛЯТЬ кластером ``` **Manager-токен — это полный контроль над кластером.** Кто его получил, тот может запускать что угодно на любом узле и читать все секреты Swarm. По последствиям это хуже утечки пароля от одной базы. Отсюда три правила: 1. **Токены не коммитятся.** Ни в скрипты автоматизации, ни в документацию, ни «временно, чтобы не забыть». 2. **Если токен где-то засветился — ротируй:** `docker swarm join-token --rotate manager`. Старый сразу перестаёт работать, уже вошедшие узлы не вылетают. 3. **Новые узлы — всегда worker**, если нет явной причины делать их manager. Проверь прямо сейчас: `grep -r "SWMTKN" .` по своим репозиториям и скриптам.
Removed
Removed
Removed
Review