Ответ
Twelve-Factor App — это набор принципов для построения современных, масштабируемых и переносимых SaaS-приложений. Эти принципы помогают создавать приложения, которые легко развертывать, масштабировать и поддерживать в облачных средах.
Ключевые принципы:
- Одна кодовая база, отслеживаемая в системе контроля версий, — множество развертываний. Один репозиторий для приложения, но разные среды (разработка, staging, production).
- Явное объявление и изоляция зависимостей. Все зависимости должны быть явно объявлены (например, в
package.json,requirements.txt,pom.xml) и никогда не подразумеваться. - Хранение конфигурации в среде выполнения. Конфигурация (ключи API, строки подключения к БД) должна храниться в переменных окружения, а не в коде.
- Сопоставление сторонних сервисов с ресурсами. Базы данных, очереди сообщений, кэш должны рассматриваться как присоединяемые ресурсы, настраиваемые через конфигурацию.
- Строгое разделение стадий сборки и выполнения. Стадия сборки преобразует код в исполняемый артефакт. Стадия выполнения запускает этот артефакт. Их нельзя смешивать.
- Запуск приложения как одного или нескольких несостоятельных процессов. Приложение выполняется как один или несколько процессов, не хранящих состояние внутри себя. Состояние сохраняется во внешних хранилищах (БД, кэш).
- Экспорт сервисов через привязку портов. Приложение должно быть самодостаточным и предоставлять свои сервисы через объявленный порт.
- Масштабирование через модель процессов. Масштабирование осуществляется путем запуска большего количества идентичных процессов (горизонтальное масштабирование).
- Быстрый запуск и корректное завершение для обеспечения надежности. Процессы должны быстро запускаться и корректно завершаться при получении сигнала (например, SIGTERM), обеспечивая устойчивость к сбоям.
- Максимальное сближение сред разработки, промежуточной и рабочей. Следует минимизировать различия между средами, чтобы избежать проблем типа "работает на моей машине".
- Журналирование как поток событий. Приложение должно выводить журналы (логи) как поток событий в
stdout. Агрегация и хранение логов — задача инфраструктуры. - Задачи администрирования запускать как разовые процессы. Задачи по обслуживанию (миграции БД, запуск скриптов) должны выполняться в той же среде, что и основное приложение, но как разовые процессы.
Пример (Принцип 3 — Конфигурация):
# Плохо: конфигурация захардкожена
DATABASE_URL = 'postgresql://user:pass@localhost/db'
# Хорошо: конфигурация берется из переменных окружения
import os
DATABASE_URL = os.environ.get('DATABASE_URL')
Следование этим принципам упрощает CI/CD, развертывание в контейнерах (Docker) и оркестрацию (Kubernetes).
Ответ 18+ 🔞
А, блядь, Twelve-Factor App! Ну это ж классика, ёпта, как будто на дворе 2002-й год, а все до сих пор про неё говорят. Слушай, это типа такой свод правил, чтобы твоё приложение не было пиздопроебибным распиздяем, который работает только у тебя на ноуте, а в продакшене накрывается медным тазом. По сути, это инструкция, как не стать тем самым чуваком, которому доверия — ноль ебать.
Вот смотри, главная идея — твой код должен быть как хитрая жопа: готов ко всему. Первый принцип — одна кодовая база. Это значит, что у тебя один репозиторий на всё приложение, а не хуй с горы разбросан по десяти разным папкам, где половина — это скрипты твоего корега, который уволился три года назад. Из этой одной базы ты уже делаешь сборки для разработки, тестов и прода.
Дальше — зависимости. Ёперный театр, сколько раз было: скачал проект, а он нихуя не запускается, потому что какому-то левому модулю нужна старая версия библиотеки, которая конфликтует со всей системой. Так вот, принцип говорит — явно объявляй все зависимости в специальном файле. package.json, requirements.txt — вот это всё. Чтобы любой идиот (или новый разработчик, что часто одно и то же) мог просто выполнить команду и получить рабочее окружение.
А вот третий принцип — это просто песня. Конфигурация в переменных окружения. Представь, у тебя в коде прямо зашиты логин и пароль от продакшен-базы. Это пиздец какой-то, чувак. Это уровень «сам от себя охуел». Надо выносить всё в переменные: строки подключения, секретные ключи, настройки. В коде остаётся только логика.
# Вот так делать — это манда с ушами. Удали это немедленно.
DATABASE_URL = 'postgresql://admin:qwerty123@prod-db.internal/super_secret_data'
# А вот так — уже похоже на человека разумного.
import os
DATABASE_URL = os.environ.get('DATABASE_URL') # Берём из окружения, и никаких паролей в гите!
Пятый принцип — разделяй сборку и запуск. Сборка — это когда ты из своего кода делаешь готовый артефакт (пакет, контейнер). Запуск — это когда этот артефакт просто берут и запускают. Нельзя во время запуска лезть в интернет и доустанавливать пакеты — это волнение ебать для всей команды девопсов.
Шестой — процессы без состояния. Твоё приложение не должно хранить в памяти сессии пользователей или загруженные файлы. Представь, у тебя два инстанса, и пользователь попал на другой — а его корзина покупок осталась на первом. Полный пиздец. Всё состояние — во внешние хранилища: база, кэш, объектное хранилище.
И самый, наверное, важный для понимания — одиннадцатый. Логирование. Приложение не должно само решать, куда писать логи — в файл server.log, в error.log, ещё куда-то. Оно должно просто вываливать поток событий в стандартный вывод (stdout). А дальше инфраструктура (Docker, Kubernetes, система логирования) сама разберётся, куда это всё складывать и как анализировать. Это гениально просто, потому что избавляет от тонн кастомного кода для ротации логов.
Если коротко, следовать этим принципам — это как не быть полупидором в разработке. Это делает приложение переносимым, его легко запустить в Docker-контейнере и оркестрировать через Kubernetes. Иначе будешь как тот самый Фарлаф, который только и думает, как бы объебать систему, а в итоге сам останешься с носом и с приложением, которое «работает только у меня».