Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → 12-factor приложение: практика

12-factor на практике: что из манифеста реально важно в 2026

Разбор 12-факторной методологии для работающих разработчиков: конфигурация в env, stateless-процессы, логи в stdout, parity окружений — и какие факторы спорны сегодня.

Прямой ответ

12-factor — манифест Heroku 2011 года, который остаётся рабочим чек-листом «сервис готов к облаку/контейнерам»; ядро, которое выполняется буквально: конфигурация в окружении (код один на все стенды, различия — env: DSN, ключи, адреса — секреты и env); сборка/релиз/запуск раздельно (образ собирается один раз — деплой = новый конфиг к тому же артефакту, а не пересборка «под прод» — multistage-сборка); процессы без состояния (сессии/файлы — во внешние хранилища: Redis/S3 — любой экземпляр заменяем мгновенно — K8s-поды смертны по построению); логи как поток в stdout (приложение не ротирует свои файлы — платформа собирает — логи); parity окружений (dev/staging/prod различаются масштабом, не архитектурой — docker-compose локально = топология прода в миниатюре); backing services как подключаемые ресурсы (БД/очереди — по адресу из конфига: смена провайдера — правка env, не кода). Спорные/эволюционировавшие пункты честно помечаются ниже — но даже «устаревший» манифест полезнее бессистемности: сервис, нарушающий 3–4 базовых фактора (конфиг в коде, состояние на диске, логи в файл с ручной ротацией), не переносится в кластер без переписывания.

Факторы, которые выполняются буквально

Codebase + Dependencies: один репозиторий — один сервис (монорепо — ок при независимых деплоях частей), зависимости объявлены явно и версионированы (pyproject+lock — «на моей машине стояло» исключается — окружения); системные зависимости — тоже в образе (apt-пакеты в Dockerfile, не «поставить руками»). Config: всё, что различается между деплоями, — в env (строки подключения, ключи, флаги стенда); то, что НЕ различается (внутренние настройки приложения), — в коде/файлах образа (раздувание env до сотни переменных — антипаттерн обратной стороны); валидация конфига при старте (отсутствующая обязательная переменная — немедленный отказ с ясным сообщением, а не TypeError в глубине через час). Build/Release/Run: релиз = образ (иммутабельный артефакт) + конфиг (подставляется при запуске) — откат = запуск предыдущего образа со старым конфигом, секундное дело; «поправили конфиг на проде руками и перезапустили» — нарушение, ведущее к дрейфу (расхождение «что в git» и «что работает»). Disposability: быстрый старт и graceful-остановка по SIGTERM (shutdown-практика) — масштабируемость и деплой без потерь держатся на этом.

Stateless, backing services, конкурентность

Stateless-процессы — самый «дорогой» фактор при нарушении: состояние в памяти/на локальном диске привязывает пользователя к экземпляру (липкие сессии, «этот сервер перезагружать нельзя — там файлы») и ломает горизонтальное масштабирование; перенос: сессии — в Redis/подписанные JWT (аутентификация), загруженные файлы — в объектное хранилище (S3/MinIO), кеш — внешний (паттерны); локальная ФС — только tmpfs-черновики на время запроса. Backing services как ресурсы: БД/Redis/Kafka подключаются по URL из конфига — код не различает «локальный Postgres» и «облачный» (compose-стек и прод — одна топология, разные адреса); смена/миграция сервиса — операционная задача, не разработка. Concurrency: масштабирование процессами (gunicorn-воркеры) и контейнерами, не потоками внутри одного (модель «толстого процесса» с внутренним пулом потоков проигрывает кластерной горизонтальности — процесс-на-задачу масштабируется и изолируется лучше; внутри — async для IO-конкурентности). Dev/prod parity: различия сокращаются (тот же Postgres версией, та же Redis-семья — docker-compose даёт локально то, что в проде managed; «в проде настоящий Kafka, локально эмулятор» — известный компромисс, риск которого снижается контрактными тестами).

Спорные пункты и современное прочтение

Честный разбор эволюции: Admin processes («одноразовые задачи как код» — миграции/скрипты в том же окружении) — выполняется и актуален (alembic-миграция из образа — практика); Port binding («приложение само терминирует HTTP») — на практике почти всегда обратное: приложение за reverse-proxy/ingress (nginx) — фактор читается как «приложение слушает порт и не требует внешнего веб-сервера как костыля», а не «никаких прокси»; Logs as stream — эволюционировал: stdout верен, но структурированный формат (JSON) добавлен практикой (манифест писался до повсеместных агрегаторов — Loki/EFK ожидают машинно-читаемое); Config в env исключительно — современный нюанс: секреты из env видны в inspect/дампах — зрелые стеки добавляют секрет-хранилища с инжекцией (Vault) — env остаётся интерфейсом доставки в процесс, но источник — защищённое хранилище. Итог: манифест — не догма, а направление: каждое отклонение должно быть осознанным (с записью «почему»), а не результатом незнания — «мы не делаем 12-factor» и «мы нарушаем пункт X вот почему и вот компенсация» — разные уровни зрелости.

Практический сценарий: аудит легаси-сервиса по факторам

Сервис: Flask 2016 года, VPS, «работает, но не масштабируется». Аудит по факторам с оценкой переделки: конфиг — settings.py с прод-значениями в git (нарушение: вынос в env — день работы, pydantic-settings с валидацией); состояние — загруженные файлы в /var/www/uploads, сессии в памяти процесса (нарушение: файлы → MinIO c presigned — два дня; сессии → Redis — день; sticky-сессии nginx выключаются после); логи — RotatingFileHandler в /var/log/app (нарушение: stdout + journald/агрегатор — час, миграция логов); сборка — git pull + pip install на сервере, зависимости без lock (нарушение: Dockerfile + lock, образ из CI — два дня); запуск — nohup python app.py (нарушение: systemd → позже контейнер — день); админ-скрипты — bash на сервере руками (нарушение: management-команды в образе — по мере касания). Итог аудита — план на две недели, после которого сервис поднимается в кластере без правок кода (конфиг — ConfigMap/Secret, файлы — S3-драйвер, логи — stdout): 12-факторность оказалась не абстракцией, а конкретным списком работ с оценками — ценность манифеста ровно в этом.

FAQ

12-factor или «cloud native» — одно и то же? Смежные: 12-factor — правила построения приложения (код/конфиг/состояние/логи); cloud native — шире: платформа и процессы вокруг (K8s, service mesh, observability, CI/CD-культура); 12-factor-приложение — предпосылка комфортной жизни в cloud-native платформе, но не гарантия (платформа может быть, а приложение с локальным состоянием в ней мучается).

Насколько строго соблюдать для внутренних инструментов? Ядро — обязательно (конфиг в env, stateless, логи в stdout — стоимость соблюдения минимальна, выигрыш при любом росте); перфекционизм по каждому пункту — по потребности (внутренний инструмент на одной ноде с локальными файлами может жить с нарушениями — пока не понадобилось масштабировать/переносить).

Что добавилось к манифесту с 2011 года? Практика дописала: структурированные логи (JSON), health-эндпоинты и пробы (healthcheck-дисциплина), graceful shutdown с дедлайнами, секреты из хранилищ вместо чистого env, идемпотентные деплои и immutable-инфраструктура — «12+ факторов» живёт в лучших практиках платформ; сам сайт манифеста не обновлялся — читать как основу, не как исчерпывающий стандарт.

Как проверить приложение на 12-факторность быстро? Тест-вопросы: сервис поднимается на чистой машине одной командой из артефакта CI? Два экземпляра за прокси работают без липкости? Удаление любого экземпляра незаметно пользователям? Конфиг прод-стенда не содержит кода, код — значений? Перенос БД на другой хост — правка env? Все «да» — факторность соблюдена в главном.

Источники: 12factor.net, Heroku 12factor repo — ссылки в шапке.