Конфигурация приложения: 12 факторов на практике
Двенадцатифакторный подход помогает отделить код от настроек, зависимостей и окружения. Разбираем, что именно меняется в проекте, где хранить секреты и почему конфигурация из файла часто ломает релиз.

Приложение редко ломается из-за одной строки кода: чаще причиной становится разный набор переменных, ручная правка конфигурации или запуск миграции не в том окружении. Двенадцатифакторный подход превращает такие настройки в управляемую систему: код остаётся одинаковым, а окружение меняется через явные параметры, сборку и процесс запуска.
Что именно описывают двенадцать факторов
Методология The Twelve-Factor App появилась для сервисов, которые разворачиваются в разных окружениях и запускаются как процессы. Это не фреймворк и не готовый конфигурационный файл. Скорее, набор проверяемых правил: если staging и production требуют разных копий исходников или ручных правок на сервере, система уже отходит от подхода.
- Одна кодовая база. Один репозиторий разворачивается в разных окружениях, а не отдельная ветка «для прода».
- Зависимости. Пакеты явно описаны и устанавливаются автоматически.
- Конфигурация. Значения, которые отличаются между окружениями, не зашиваются в исходный код.
- Внешние сервисы. База, очередь, объектное хранилище и почтовый провайдер подключаются как заменяемые ресурсы.
- Сборка, релиз и запуск. Артефакт собирается отдельно, получает версию и затем запускается без пересборки на сервере.
- Процессы. Приложение не рассчитывает на локальное состояние процесса как на постоянное хранилище.
- Привязка к порту. Веб-сервис сам слушает порт и не требует особой настройки веб-сервера для работы как приложения.
- Масштабирование процессами. Нагрузка распределяется между экземплярами или типами процессов.
- Быстрый запуск и остановка. Процесс умеет корректно завершаться и подниматься заново.
- Сходство окружений. Разрыв между разработкой, тестированием и production сокращается по инструментам и процедурам.
- Логи как поток событий. Приложение пишет логи в stdout или stderr, а сбор и хранение выполняет внешняя система.
- Административные задачи. Миграции, импорт и разовые команды запускаются тем же кодом и с теми же настройками, что и основной процесс.
Для конфигурации особенно важны факторы 3, 4, 5, 10 и 12. Остальные нужны потому, что настройки не живут отдельно: способ сборки, подключение базы и запуск миграций напрямую влияют на результат.
Хорошая конфигурация — это не набор файлов с параметрами. Это воспроизводимый контракт между кодом, окружением и процессом запуска.
Пояснение к термину: backing service — внешний ресурс, которым приложение пользуется по сети: база данных, очередь, хранилище файлов, SMTP-сервис или сторонний API. Для приложения они должны выглядеть как подключаемые зависимости, а не как часть конкретного сервера.
Фактор конфигурации: что выносить из кода
В конфигурацию попадают значения, которые меняются между окружениями или не должны храниться в репозитории. Это адрес базы, имя очереди, уровень логирования, режим отладки, публичный URL, тайм-ауты и лимиты внешних запросов. Алгоритм обработки заказа или имя таблицы, напротив, не становятся переменными только потому, что их удобно менять через окружение.
В приложении можно использовать переменные окружения с понятными именами. Например, минимальный набор для веб-сервиса выглядит так:
APP_ENV=production
HTTP_PORT=8080
DATABASE_URL=postgresql://app:YOUR_PASSWORD@db:5432/app
LOG_LEVEL=info
PUBLIC_BASE_URL=https://example.com
Этот фрагмент не должен автоматически становиться файлом, который коммитят в Git. Значение DATABASE_URL содержит секрет, поэтому в репозитории хранят шаблон без пароля, а реальные значения передают средствами окружения или секрет-хранилища.
Что проверять при старте
Приложение должно быстро сообщить о пропущенной обязательной переменной и завершиться с ненулевым кодом. Молчаливый переход к localhost, пустой строке или небезопасному значению создаёт более дорогую ошибку: сервис запускается, но ломается только при первом запросе.
Проверяйте также типы. Порт, тайм-аут и число повторных попыток должны преобразовываться в число, флаг отладки — в логическое значение, а URL — проходить синтаксическую проверку. Нельзя считать непустую строку «false» тем же самым, что логическое значение false.
Где хранить настройки: три рабочих варианта
У универсального решения нет. Выбор зависит от модели развертывания, требований к секретам и того, как часто настройки меняются.
| Подход | Когда использовать | Цена и риск |
|---|---|---|
| Переменные окружения | Контейнеры, CI/CD, небольшие и средние сервисы | Просто подключить, но неудобно управлять большими вложенными структурами и отслеживать изменения |
| Файл, смонтированный при запуске | Сложные YAML или JSON-настройки, локальная инфраструктура, legacy-системы | Удобно читать и версионировать шаблон, но нужно контролировать права доступа, путь и обновление файла |
| Секрет-хранилище или сервис конфигурации | Несколько окружений, аудит, ротация секретов, централизованное управление | Меньше секретов на диске, но появляется зависимость от доступности хранилища и его клиента |
На практике эти варианты комбинируют: обычные параметры передают через окружение, секреты получают из секрет-хранилища, а крупные структуры монтируют как файл. Важно не смешивать источники без правила приоритета. Если одно и то же значение приходит из файла, окружения и аргумента запуска, документация должна явно сказать, какое из них побеждает.
Сборка, релиз и запуск без ручных правок
Пятый фактор требует разделять три операции. Сборка устанавливает зависимости и создаёт артефакт. Релиз соединяет этот артефакт с конфигурацией конкретного окружения. Запуск выполняет уже подготовленный релиз. Если инженер заходит на сервер и вручную редактирует файл внутри собранного образа, следующий запуск перестаёт быть воспроизводимым.
Хорошая проверка — собрать один и тот же артефакт для тестового окружения и production, меняя только внешние значения. Если для production нужна другая версия исходников, отдельный набор пакетов или ручная правка файла после сборки, проблема находится не в конфигурации как таковой, а в нарушении границы между сборкой и запуском.
Как не превратить окружение в ловушку
- Храните в репозитории шаблон конфигурации с безопасными примерами и описанием обязательных ключей.
- Проверяйте конфигурацию до запуска приложения, а не после первого пользовательского запроса.
- Не выводите секреты в логи, сообщения об ошибках, дампы окружения и страницы диагностики.
- Фиксируйте, какой релиз и какой набор конфигурации использовались при запуске.
- Разделяйте публичные параметры и секреты: URL сервиса может быть обычной настройкой, пароль — нет.
Внешние сервисы и состояние процесса
Фактор подключаемых сервисов часто нарушают незаметно. Например, приложение считает локальный каталог постоянным хранилищем загруженных файлов, а после перезапуска контейнера файлы исчезают. То же относится к локальной памяти процесса: кэш в памяти одного экземпляра не должен быть единственным источником важных данных.
Проверьте каждую зависимость вопросом: можно ли заменить её адрес, учётные данные и тип без изменения бизнес-логики? Для базы данных ответ обычно положительный. Для жёстко зашитого пути к локальному файлу — нет. Инвалидация кэша и выбор конкретного брокера сообщений — отдельные темы; здесь важен только контракт подключения.
Логи, процессы и админские команды
Если приложение пишет логи только в локальный файл, оператору приходится угадывать, где искать данные после переноса или перезапуска. Лучше отдавать структурированные события в stdout/stderr, а маршрутизацию, ротацию и хранение поручать платформе.
Миграции базы и импорт данных должны запускаться тем же кодом и с теми же переменными, что и веб-процесс. Отдельная «ручная» версия настроек для административной команды — частый источник несовместимых схем и неочевидных ошибок.
Что ломается первым
- Одинаковая переменная имеет разные значения. В одном окружении
LOG_LEVEL=INFO, в другом ожидается только нижний регистр. Нормализуйте значение в одном месте и документируйте допустимые варианты. - Секрет оказался в образе или Git. Удаление строки из последнего коммита не гарантирует удаления из истории. После утечки секрет нужно отозвать и заменить, а не только переименовать переменную.
- Конфигурация меняется без релиза. Быстрый ручной фикс помогает сейчас, но через неделю невозможно восстановить причину поведения. Изменения должны проходить через журнал, ревью или систему управления конфигурацией.
- Процессы видят разные настройки. Веб-сервис получил новый адрес базы, а worker продолжил работать со старым. Перезапускайте весь набор связанных процессов атомарно или проверяйте версию конфигурации.
- Сервис стартует с небезопасными значениями по умолчанию. Такой fallback допустим только для локальной разработки и должен быть явно запрещён в production.
Когда какой подход выбирать
Для одного сервиса с контейнерным запуском начните с переменных окружения и шаблона конфигурации. Если параметров становится много, не переносите всё в один гигантский JSON: сгруппируйте значения по подсистемам и добавьте проверку схемы.
Секрет-хранилище оправдано, когда нужна ротация без ручной рассылки файлов, аудит доступа или единое управление несколькими окружениями. Монтируемые файлы полезны для сертификатов, политик и больших структур, которые неудобно представлять плоскими переменными. Но файл не отменяет проверку прав и контроль версии.
Критерий выбора простой: переменная окружения подходит для небольшого атомарного значения, файл — для структурированных данных, секрет-хранилище — когда главным требованием становится жизненный цикл секрета и аудит.
Что сделать дальше
Составьте таблицу всех настроек приложения: источник, обязательность, тип, окружение и владелец. Затем удалите из кода значения, которые меняются между средами, добавьте проверку старта и прогоните полный цикл на чистом окружении. После первого релиза измеряйте не только ошибки приложения, но и время восстановления после изменения конфигурации: именно там становится видно, воспроизводима ли ваша система.
Логотип и фирменный стиль: Три концепции разного характера, палитра с обоснованием, проверка на читаемость в малом размере и в один цвет.
Спросить за 60 ₽Источники: The Twelve-Factor App — официальный сайт методологии, The Twelve-Factor App: Config
Частые вопросы
Обязательно ли использовать только переменные окружения?
Можно ли хранить файл .env в репозитории?
Что произойдёт, если обязательная переменная не задана?
Нужно ли перезапускать приложение после изменения конфигурации?
Как понять, что проект действительно следует двенадцати факторам?
Что делать, если конфигурация уже разбросана по коду, файлам и серверу?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.