От Compose к оркестрации: когда контейнеров становится много

Рейтинг: 48.7% · 7 голосов
Практический курс по Docker: образы, контейнеры, тома, сети, Compose и продакшен. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
Marina_DevOps
Сообщения: 54
Зарегистрирован: 11 май 2026, 05:31

От Compose к оркестрации: когда контейнеров становится много

Сообщение Marina_DevOps »

Оглавление курса (46)
  1. Что такое Docker и какие задачи он решает
  2. Установка Docker и запуск первого контейнера
  3. Образы: слои, теги и реестр Docker Hub
  4. Пишем свой Dockerfile
  5. Тома и хранение данных: volumes и bind mounts
  6. Сети в Docker: связываем контейнеры между собой
  7. Переменные окружения и конфигурация контейнеров
  8. Docker Compose: поднимаем многоконтейнерное приложение
  9. Оптимизация образов: multi-stage сборка, размер и кэш слоёв
  10. Логи, отладка и мониторинг контейнеров
  11. Базовая безопасность контейнеров
  12. Подготовка к продакшену: что важно учесть
  13. Dockerfile глубже: ENTRYPOINT и CMD, HEALTHCHECK, .dockerignore, запуск не от root
  14. Реестры образов: приватные registry, push и pull, теги и digest, imagePullSecrets
  15. BuildKit и buildx: multi-arch сборки, секреты сборки, экспорт кэша
  16. Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация
  17. Итоговый проект и куда расти: от Dockerfile до прода, обзор оркестрации (Kubernetes, Podman, OCI)
  18. Архитектура Docker: dockerd, containerd, runc и OCI
  19. Как работает изоляция: namespaces и cgroups
  20. Образы изнутри: слои, OverlayFS и storage driver
  21. Жизненный цикл контейнера и политики перезапуска
  22. Отладка контейнеров: exec, attach, nsenter, debug
  23. Сети Docker глубже: bridge, overlay, macvlan и iptables
  24. Docker Compose глубже: profiles, healthcheck-зависимости, override
  25. Данные и тома глубже: драйверы, бэкап, права
  26. Секреты и конфигурация: как не светить пароли
  27. Ограничение ресурсов: CPU, память, OOM и cgroups
  28. Здоровье и автозапуск: HEALTHCHECK, init и сигналы
  29. Логирование контейнеров: драйверы, ротация, сбор
  30. Мониторинг контейнеров: stats, cAdvisor, Prometheus
  31. Безопасность глубже: rootless, user namespaces, seccomp, capabilities
  32. Supply chain: сканирование, SBOM и подпись образов
  33. Глубокая оптимизация образов: distroless, scratch, кэш
  34. Multi-arch и сборка под ARM: buildx и эмуляция
  35. Реестры в продакшене: Harbor и облачные registry
  36. Docker без Docker: Podman, containerd, nerdctl, Buildah
  37. От Compose к оркестрации: когда контейнеров становится много (вы здесь)
  38. Docker Swarm: встроенная оркестрация
  39. Сборка образов в CI без демона: kaniko, BuildKit, Buildah
  40. Траблшутинг Docker: типичные ошибки и как чинить
  41. Производительность и эксплуатация Docker-хоста
  42. Docker Desktop, WSL2 и альтернативы на Windows и Mac
  43. Контейнеризация приложений: бэкенд, фронтенд, БД
  44. Docker и Kubernetes: containerd, миграция, kompose
  45. Лучшие практики и антипаттерны Docker
  46. Сквозной проект: production-ready стек и путь дальше
Боль, с которой ты столкнешься рано или поздно

У тебя есть compose.yaml. Один сервер. Ты делаешь

Код: Выделить всё

docker compose up -d
, и весь стек - api, postgres, redis, nginx - живет на одной машине. Это работает. Для dev, для staging, для маленького pet-проекта это просто идеально: один файл описывает всю систему, поднял за секунды, снес за секунды.

А потом приходит реальность. Сервер уходит в перезагрузку посреди ночи - и весь твой прод лежит, пока ты не проснешься. Трафик вырос вдвое - и ты упираешься в потолок CPU одной коробки, а вертикально расти уже некуда или дорого. Тебе нужно выкатить новую версию без даунтайма - а

Код: Выделить всё

docker compose up
просто гасит старый контейнер и поднимает новый, и в эту дырку в пару секунд падают запросы клиентов. Один сервис течет по памяти и его надо рестартить по расписанию - и ты пишешь костыль на cron.

Вот тут и начинается тема docker оркестрации. Это не про новую модную игрушку - это про то, что Compose сознательно решает другую задачу, и в какой-то момент ты вырастаешь из его границ. Давай разберем честно: где проходит граница, что именно Compose не умеет, и какой инструмент берут вместо него - Docker Swarm, Kubernetes или Nomad. И главное - как понять, что тебе вообще пора.

Изображение

Что Compose решает, а что нет

Compose - это инструмент описания и запуска многоконтейнерного приложения на одном Docker-хосте. Он читает compose.yaml, создает сеть, тома, поднимает контейнеры в нужном порядке (через depends_on и healthcheck), связывает их по именам сервисов через встроенный DNS. В этом он великолепен. Но вся его модель мира заканчивается на границе одной машины.

Разберем по пунктам, что compose в проде не закрывает:
  • Отказоустойчивость узла. Упал сервер - упало все. Compose не знает про другие машины, ему некуда переехать. Нет понятия "запасной узел".
  • Авто-восстановление сервиса. Тут нюанс:

    Код: Выделить всё

    restart: always
    перезапустит контейнер, если процесс внутри умер или хост перезагрузился. Но это тупой рестарт на том же месте. Если упала вся машина целиком - перезапускать некому. И если контейнер "жив, но не отвечает" (завис, healthcheck красный) - сам по себе restart-policy его не пересоздаст, он реагирует на код выхода процесса, а не на здоровье.
  • Балансировка по узлам. Распределить десять реплик сервиса по трем серверам так, чтобы нагрузка размазалась - Compose этого не делает в принципе. Все реплики живут на одном хосте.
  • Горизонтальное docker масштабирование под нагрузку. Да, есть

    Код: Выделить всё

    docker compose up --scale api=4
    . Но это четыре копии на одной машине, без авто-скейла по метрикам, без переноса на свободные узлы.
  • Rolling-апдейты на кластере. Выкатить новую версию по одной реплике, проверяя healthcheck, и откатиться при сбое - Compose так не умеет. Он гасит и поднимает, точка.
Ключевая мысль: оркестратор - это планировщик (scheduler), который видит пул машин как единый ресурс. Ты говоришь ему декларативно "хочу 5 реплик этого сервиса, всегда живых, размазанных по узлам", а он сам решает, где их запустить, следит за их здоровьем, пересоздает упавшие, переносит с умершего узла на живой. Compose говорит "запусти вот это здесь". Оркестратор говорит "обеспечь, чтобы это состояние существовало в кластере, и удерживай его". Разница принципиальная: императив против декларации желаемого состояния.

Когда Compose плюс один сервер - это правильный выбор

Сразу убьем вредный миф: "раз есть Kubernetes, Compose в проде - это несерьезно". Чушь. Огромное количество живых продакшенов годами крутятся на Compose и одном-двух серверах, и это осознанное инженерное решение, а не бедность. Более того, по опросам последних лет доля Compose-развертываний среди практикующих разработчиков даже подрастает - люди, которые шипят продукт, а не пилят платформу, не хотят платить налог сложности кубера.

Compose плюс один (или вертикально мощный) сервер - твой выбор, когда:
  • Проект небольшой: один-два сервиса, предсказуемая нагрузка, нет пиков в десятки раз.
  • Допустим короткий даунтайм. Если падение на 5-10 минут раз в полгода не стоит тебе контракта - не плати за отказоустойчивость кластера.
  • dev и staging-окружения - тут Compose почти всегда оптимален, его и не надо ничем заменять.
  • Команда маленькая и без выделенного DevOps. Кубер требует, чтобы кто-то его кормил и лечил.
Простой и честный прод на Compose усиливается малой кровью: ставишь

Код: Выделить всё

restart: unless-stopped
на сервисы, прописываешь healthcheck, кладешь reverse-proxy (nginx/traefik/caddy) спереди, настраиваешь бэкапы тома с БД и мониторинг с алертами. Этого хватает дольше, чем кажется. Не тащи кластер туда, где он не нужен - это самый дорогой антипаттерн в индустрии.

Три варианта: Swarm, Kubernetes, Nomad

Когда одного хоста перестает хватать, выбор по сути из трех. Разберем спор docker swarm vs kubernetes и третьего тихого игрока - Nomad.

Docker Swarm - оркестратор, встроенный прямо в Docker Engine. Включается одной командой

Код: Выделить всё

docker swarm init
. Его огромный плюс - почти нулевой порог входа: ты уже знаешь Compose, а Swarm читает практически тот же compose.yaml через

Код: Выделить всё

docker stack deploy
. Он дает кластер из нескольких узлов, реплики, встроенную балансировку (routing mesh), rolling-апдейты, секреты, overlay-сети между узлами. Минусы: экосистема маленькая, развитие почти остановилось, по рынку Swarm занимает единицы процентов. Хорошая новость - он не мертв: поддержка заявлена надолго (Mirantis обещает сопровождать Swarm минимум до 2030 года), так что для стабильного docker кластера среднего размера это рабочий и дешевый по сложности инструмент.

Kubernetes (k8s) - индустриальный стандарт, держит порядка 90% рынка оркестрации. Это не "запускалка контейнеров", а целая платформа: декларативные манифесты, авто-скейл по метрикам (HPA), self-healing, rolling/canary-апдейты, богатейшая экосистема (Helm, операторы, service mesh, Ingress-контроллеры). Цена - сложность. У тебя появляются Pod, Deployment, Service, Ingress, ConfigMap, namespace и десятки других сущностей, control plane, etcd, который надо беречь. Кубер окупается на масштабе, в мульти-облаке, при сотнях сервисов и командах, которым нужна стандартизация. На трех контейнерах это из пушки по воробьям. Кстати, важная деталь 2026 года: сам Kubernetes давно не использует Docker как рантайм - он выкинул прослойку dockershim еще в версии 1.24 и работает напрямую с containerd или CRI-O через интерфейс CRI. Так что "Docker против Kubernetes" - ложная дихотомия: ты собираешь OCI-образ Docker'ом, а запускает его в кластере containerd. Они на разных слоях.

HashiCorp Nomad - легковесный планировщик, который умеет оркестрировать не только контейнеры, но и обычные бинарники, Java-приложения, QEMU-вм. Один компактный бинарь, проще кубера, отлично дружит с Consul и Vault. Ниша - там, где нужен оркестратор, но кубер избыточен, и где в зоопарке не только контейнеры. Сообщество меньше, чем у k8s, но инструмент зрелый.

Грубое правило: Swarm - "мне нужен кластер, но без боли"; Kubernetes - "мне нужен стандарт, масштаб и экосистема, я готов платить сложностью"; Nomad - "мне нужно просто и не только про контейнеры".

Практика: Compose к Swarm и Compose к Kubernetes

Главная ценность твоего compose.yaml - он не выбрасывается при переезде. Покажу оба пути.

Путь 1: Compose к Swarm через секцию deploy. Swarm читает тот же файл, но активирует в нем секцию , которую обычный

Код: Выделить всё

docker compose
на одном хосте игнорирует. Вот фрагмент:

Код: Выделить всё

services:
  api:
    image: registry.example.ru/myapp:1.4.2
    ports:
      - "8080:8080"
    deploy:
      replicas: 4
      update_config:
        parallelism: 1
        delay: 10s
        order: start-first
        failure_action: rollback
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.role == worker
Здесь

Код: Выделить всё

replicas: 4
- держать 4 живых копии всегда;

Код: Выделить всё

parallelism: 1
с

Код: Выделить всё

delay: 10s
- обновлять по одной реплике с паузой (вот они, rolling-апдейты);

Код: Выделить всё

order: start-first
- сперва поднять новую реплику, потом погасить старую (это и есть выкатка без даунтайма, в отличие от поведения Compose).

Код: Выделить всё

failure_action: rollback
- если новая версия не прошла healthcheck, Swarm сам откатится. Деплой:

Код: Выделить всё

docker swarm init
docker stack deploy -c compose.yaml myapp
docker stack services myapp
Разбор вывода последней команды:

Код: Выделить всё

ID             NAME         MODE         REPLICAS   IMAGE                              PORTS
k3p9x2f1abcd   myapp_api    replicated   4/4        registry.example.ru/myapp:1.4.2   *:8080->8080/tcp
Смотри на колонку REPLICAS: значит "запущено 4 из желаемых 4" - кластер в нужном состоянии. Если увидишь - одна реплика не поднялась (нет места на узлах, упал healthcheck, не скачался образ), и Swarm будет пытаться добить до четырех. MODE replicated - фиксированное число копий; бывает global - по одной на каждый узел (удобно для агентов мониторинга).

Путь 2: Compose к Kubernetes через kompose. Здесь нельзя просто скормить compose.yaml кластеру - нужны манифесты k8s. Утилита (официальный проект Kubernetes, актуальная версия линейки 1.38) конвертирует автоматически:

Код: Выделить всё

kompose convert -f compose.yaml -o k8s/
Из одного сервиса она породит Deployment, Service, при наличии томов - PersistentVolumeClaim, из переменных - ConfigMap. Но трезво: kompose дает процентов 70-80 готового, остальное доводишь руками. Две ключевые ловушки. Первая - игнорируется: образы должны быть заранее собраны и запушены в registry (k8s не собирает образы, он их только запускает). Вторая - после конвертации обязательно добавь то, чего в compose обычно нет: liveness/readiness-пробы, resource requests/limits, нормальные секреты вместо открытых env, NetworkPolicy. Сгенерированный манифест - это черновик, а не финал.

Грабли и антипаттерны
  • Тащить Kubernetes на три контейнера. Самая частая и дорогая ошибка. Ты платишь сложностью каждый день, а выгоду масштаба не получаешь. Сначала вырасти из Compose по реальным причинам, потом выбирай.
  • Думать, что restart: always - это и есть отказоустойчивость. Нет. Это перезапуск процесса на том же хосте. Упала машина - перезапускать некому. Настоящая отказоустойчивость живет только на уровне кластера из нескольких узлов.
  • Считать, что compose.yaml = манифесты k8s. Для Swarm файл переиспользуется почти целиком. Для Kubernetes - это совсем другая модель сущностей, kompose лишь стартовая точка.
  • Игнорировать stateful-данные при переезде. Базу данных в кластер тащить опаснее всего: тома, привязка к узлу, бэкапы, репликация - отдельная большая тема. Часто БД оставляют как managed-сервис или на выделенной машине, а в кластер выносят stateless-сервисы.
  • Забыть про реестр образов. В кластере каждый узел сам тянет образ. Локальной сборки мало - образ должен лежать в доступном всем узлам registry. В RU-реалиях, когда Docker Hub бывает капризен, держи приватный реестр или зеркало (Yandex Container Registry, VK Cloud, Harbor у себя).
Мини-лаба: пощупай границу руками

Все делается на одной машине с установленным Docker, кластер из одного узла - этого хватит, чтобы увидеть разницу.
  • Возьми любой свой compose.yaml с одним web-сервисом. Подними обычным

    Код: Выделить всё

    docker compose up -d
    , проверь

    Код: Выделить всё

    docker compose ps
    . Это твоя точка отсчета.
  • Добавь в сервис секцию с

    Код: Выделить всё

    replicas: 3
    и

    Код: Выделить всё

    update_config
    как в примере выше.
  • Выполни

    Код: Выделить всё

    docker swarm init
    , затем

    Код: Выделить всё

    docker stack deploy -c compose.yaml lab
    . Посмотри

    Код: Выделить всё

    docker stack services lab
    - убедись, что REPLICAS показывает 3/3.
  • Грохни один контейнер реплики:

    Код: Выделить всё

    docker rm -f <id>
    . Через пару секунд снова глянь

    Код: Выделить всё

    docker stack services lab
    - Swarm пересоздал убитую реплику сам. Вот оно, желаемое состояние в действии, чего Compose не делает.
  • Поменяй тег образа на новый и снова

    Код: Выделить всё

    docker stack deploy
    - понаблюдай через

    Код: Выделить всё

    docker service ps lab_web
    , как реплики обновляются по одной (rolling).
  • Бонус: поставь и сделай

    Код: Выделить всё

    kompose convert -f compose.yaml -o k8s/
    . Открой сгенерированные файлы и найди глазами, чего там не хватает для прода - проб, лимитов, секретов.
  • Прибери за собой:

    Код: Выделить всё

    docker stack rm lab
    и

    Код: Выделить всё

    docker swarm leave --force
    .
Контрольные вопросы
  • Назови минимум три вещи, которые Compose на одном хосте принципиально не решает, и объясни почему - в чем ограничение его модели.
  • Чем

    Код: Выделить всё

    restart: always
    отличается от настоящей отказоустойчивости на уровне кластера? В каком случае он бесполезен?
  • Почему compose.yaml почти без правок едет в Swarm, но требует конвертации для Kubernetes? Что именно делает kompose и где его предел?
  • Сформулируй критерии, по которым ты в реальном проекте выберешь Swarm, Kubernetes или останешься на Compose плюс один сервер.
Итог

Compose - чемпион одного хоста, и для dev, staging и небольшого прода он часто оптимален; не меняй его без реальной причины. Граница наступает, когда тебе нужны отказоустойчивость узлов, авто-восстановление в масштабах кластера, балансировка по машинам и rolling без даунтайма - этого один хост не дает. Тогда выбираешь: Swarm как дешевый по сложности шаг (тот же compose.yaml плюс deploy), Kubernetes как индустриальный стандарт ценой сложности, Nomad как легковесную середину. И помни: Docker и Kubernetes - не конкуренты, а соседние слои; образ ты по-прежнему собираешь Docker'ом, а в кластере его крутит containerd. В следующем большом блоке мы пойдем вглубь именно в Kubernetes - разберем Pod, Deployment, Service и то, как все это удерживает твое желаемое состояние.
👍3 ❤️ 🔥1 😄 🤔
Аватара пользователя
rd40
Сообщения: 1
Зарегистрирован: 02 июн 2026, 01:38

Re: От Compose к оркестрации: когда контейнеров становится много

Сообщение rd40 »

Сидел год на compose в проде и стеснялся этого, как будто делаю что-то стыдное. После урока выдохнул - у меня как раз два сервиса и редкий трафик, кубер бы только сожрал время. Спасибо что прямо сказали не тащить его без причины.
👍1 ❤️ 🔥 😄 🤔
Аватара пользователя
mandor
Сообщения: 1
Зарегистрирован: 08 июн 2026, 12:27

Re: От Compose к оркестрации: когда контейнеров становится много

Сообщение mandor »

А вот момент с order start-first прям золото, я раньше ловил пятисекундные дырки на деплое и думал что так и надо. Получается в Swarm это из коробки решается через update_config? Пойду пробовать на стейдже.
👍 ❤️ 🔥 😄 🤔1
Ответить
← Предыдущая глава
Docker без Docker: Podman, containerd, nerdctl, Buildah
Следующая глава →
Docker Swarm: встроенная оркестрация

Все главы курса «Docker: контейнеризация от основ до продакшена»

Поделиться темой: ✈ Telegram VK
Похожие запросы: podman vs docker что выбрать в продеdocker swarm встроенная оркестрация или kubernetesdocker network как связать контейнеры между собой по имени

Вернуться в «Docker с нуля»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость