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

#1
open+284proposed by devops · Aug 14, 2026 · based on v1
Proposed changes · v1 → suggestion
+1194
1¶ # С чего начинается путаница
2
3 Типичный вопрос после перехода на Swarm: «место на диске не освободилось, контейнеры появились на втором сервере, docker-compose теперь не нужен?»
4
5 Короткий ответ: **всё запущено дважды**. Старые контейнеры от `docker-compose` никуда не делись, а рядом появились сервисы Swarm. Они не видят друг друга и едят ресурсы одновременно.
6
7 Список непоследовательный — читай то, что нужно.
8¶ ## Два разных мира
9
10 | | `docker compose up` | `docker stack deploy` |
11 |---|---|---|
12 | Что создаёт | контейнеры | сервисы |
13 | Где запускает | только на этой машине | на любом узле кластера |
14 | Чем смотреть | `docker ps` | `docker service ls` |
15 | При падении | лежит, пока не поднимешь | перезапускается сам |
16 | Масштабирование | вручную | `replicas: N` |
17
18 **Главное:** `docker ps` показывает **и** контейнеры Swarm, **и** обычные. Поэтому по одному `docker ps` нельзя понять, что чем управляется — и именно отсюда ощущение, что «всё как-то странно».
1+## Проверка
2+• Проверить актуальную версию Docker
3+ Убедитесь, что у вас установлена последняя версия Docker, так как некоторые команды могут изменяться с обновлениями.
4+ $ docker --version
5+ why: Актуальная версия Docker обеспечивает поддержку всех новых функций и исправлений.
196## Разобраться
207• Понять, что управляется Swarm, а что нет
218 Сначала смотрим сервисы кластера:
229
2310 ```bash
2411 docker stack ls # список стеков
2512 docker service ls # сервисы и их реплики
2613 docker node ls # узлы кластера
2714 ```
2815
2916 Потом — все контейнеры на машине:
3017
3118 ```bash
3219 docker ps
3320 ```
3421
3522 У контейнеров Swarm имена вида `стек_сервис.1.длинныйидентификатор`. У обычных — простые, из compose-файла. Это самый быстрый способ их различить.
3623 $ docker service ls
3724 why: Пока не разделишь эти два мира в голове, любая отладка превращается в гадание: останавливаешь контейнер, а он поднимается снова — потому что это сервис Swarm, и кластер честно восстанавливает заданное число реплик.
3825 - [ ] Ты можешь назвать, какие контейнеры на машине от Swarm, а какие нет
3926 - [ ] Понимаешь, почему остановленный контейнер Swarm поднимается сам
4027 → Docker Swarm — обзор — https://docs.docker.com/engine/swarm/
4128 → Управление сервисами — https://docs.docker.com/engine/swarm/services/
4229• Остановить дублирующие контейнеры
4330 Когда сервис уже живёт в Swarm, старый контейнер надо гасить тем же инструментом, которым поднимали:
4431
4532 ```bash
4633 # если поднимали через compose
4734 docker compose -f путь/к/docker-compose.yml down
4835
4936 # если вручную
5037 docker stop имя && docker rm имя
5138 ```
5239
5340 **Не пытайся** гасить через `docker stop` контейнер Swarm-сервиса — кластер тут же создаст новый. Нужно `docker service scale имя=0` или `docker stack rm`.
5441 $ docker ps --format "{{.Names}}"
5542 why: Два комплекта одних и тех же сервисов — это не только двойной расход памяти. Это ещё и два приложения, пишущих в одну базу, и два планировщика, выполняющих одни и те же фоновые задачи.
5643 - [ ] Каждый сервис запущен ровно один раз
5744 - [ ] Старые compose-контейнеры остановлены тем же инструментом, которым поднимались
58¶ ## Распределение между manager и worker
59
60 В кластере есть узлы двух ролей. Manager держит состояние кластера и принимает решения, worker — просто запускает задачи.
61
62 Рабочее правило распределения:
63
64 | Что | Куда | Почему |
65 |---|---|---|
66 | Инфраструктура кластера, панель управления, прокси | **Manager** | без них кластером не поуправляешь |
67 | Базы данных | **Manager** | стабильность важнее гибкости, данные привязаны к тому узла |
68 | Кэш (Redis и подобные) | **Worker** | лёгкие, перезапуск безболезненен |
69 | Бэкенды | **Worker** | тяжёлые по CPU, их много |
70 | Фронтенды, статика | **Worker** | лёгкие, легко масштабируются |
71
72 Закрепляется в compose через ограничения размещения:
73
74 ```yaml
75 services:
76 api:
77 deploy:
78 replicas: 2
79 placement:
80 constraints:
81 - node.role == worker
82
83 postgres:
84 deploy:
85 replicas: 1
86 placement:
87 constraints:
88 - node.role == manager
89 ```
90
91 **Критично для баз данных:** если сервис с томом переедет на другой узел, том за ним не поедет — он привязан к машине. Получишь пустую базу и очень неприятный вечер.
45+ Проверить состояние сервисов после остановки
46+ После остановки дублирующих контейнеров убедитесь, что все сервисы работают корректно.
47+ $ docker service ls
48+ why: Проверка состояния сервисов предотвращает возможные ошибки в работе приложений.
49+ - [ ] Все сервисы в состоянии RUNNING
50+ - [ ] Нет остановленных или неработающих сервисов
9251## Работа со Swarm
9352• Развернуть стек
9453 ```bash
9554 docker stack deploy -c docker-compose.yml имя-стека
9655 ```
9756
9857 Тот же файл, что и для compose, но часть полей работает иначе:
9958
10059 - раздел `deploy` читается только в Swarm, compose его игнорирует;
10160 - `build` в Swarm не работает — образ должен быть уже собран и доступен всем узлам;
10261 - `depends_on` игнорируется — порядок запуска не гарантируется.
10362 $ docker stack deploy -c docker-compose.yml myapp
10463 why: Последние два пункта ловят почти всех. Локально собранный образ есть только на одном узле — на остальных сервис просто не запустится, и ошибка будет про отсутствующий образ, а не про сборку.
10564 - [ ] Стек виден в docker stack ls
10665 - [ ] Все сервисы в состоянии N/N
10766 → Развёртывание стека — https://docs.docker.com/engine/swarm/stack-deploy/
10867• Понять, почему сервис не поднимается
10968 Если `docker service ls` показывает `0/1`, смотри историю задач:
11069
11170 ```bash
11271 docker service ps имя-сервиса --no-trunc
11372 ```
11473
11574 Колонка `CURRENT STATE` и `ERROR` обычно говорят всё. Типичные состояния:
11675
11776 - **Rejected** — узел отказался: нет образа, не сошлись ограничения размещения, нет ресурсов
11877 - **Failed** — контейнер запустился и упал с ненулевым кодом
11978 - **Complete** — контейнер вышел с кодом 0. При `restart_policy: on-failure` кластер его НЕ поднимет, и сервис так и останется 0/1
12079
12180 Логи сервиса целиком: `docker service logs имя --tail 50`
12281 $ docker service ps имя-сервиса --no-trunc
12382 why: Состояние `Complete` сбивает с толку сильнее всего: выглядит как успех, а сервис лежит. Зная эти три слова, ты сэкономишь часы.
12483 - [ ] Ты знаешь, чем отличаются Rejected, Failed и Complete
12584 - [ ] Умеешь смотреть логи сервиса, а не контейнера
126¶ ## Шпаргалка по командам
127
128 ```bash
129 # обзор
130 docker node ls # узлы кластера и их роли
131 docker stack ls # стеки
132 docker service ls # сервисы и реплики
133
134 # конкретный сервис
135 docker service ps имя --no-trunc # где запущен и что с ним было
136 docker service logs имя --tail 50 # логи
137 docker service inspect имя # полная конфигурация
138
139 # изменения
140 docker service scale имя=3 # число реплик
141 docker service update --force имя # перезапустить задачи
142 docker stack deploy -c file.yml стек # развернуть или обновить
143 docker stack rm стек # снести стек целиком
144 ```
145
146 Заметь: `docker stack deploy` с тем же именем стека не создаёт второй стек, а обновляет существующий. Это и есть штатный способ выкатки.
147¶ ## О безопасности кластера
148
149 Чтобы узел вошёл в кластер, нужен **join-токен**. Их два вида, и разница между ними огромная:
150
151 ```bash
152 docker swarm join-token worker # может только выполнять задачи
153 docker swarm join-token manager # может УПРАВЛЯТЬ кластером
154 ```
155
156 **Manager-токен — это полный контроль над кластером.** Кто его получил, тот может запускать что угодно на любом узле и читать все секреты Swarm. По последствиям это хуже утечки пароля от одной базы.
157
158 Отсюда три правила:
159
160 1. **Токены не коммитятся.** Ни в скрипты автоматизации, ни в документацию, ни «временно, чтобы не забыть».
161 2. **Если токен где-то засветился — ротируй:** `docker swarm join-token --rotate manager`. Старый сразу перестаёт работать, уже вошедшие узлы не вылетают.
162 3. **Новые узлы — всегда worker**, если нет явной причины делать их manager.
163
164 Проверь прямо сейчас: `grep -r "SWMTKN" .` по своим репозиториям и скриптам.
165
166
167
Review