Принцип единой кодовой базы для всех развёртываний приложения
Одна кодовая база в системе контроля версий, множество развёртываний
Codebase — это фундамент 12-Factor методологии. Принцип гласит:
Существует ровно одна кодовая база приложения в системе контроля версий (Git). Из этой кодовой базы развёртываются все окружения: development, staging, production.
✅ Правильно:
┌─────────────────┐
│ Git Repo │
│ (one codebase)│
└────────┬────────┘
│
┌────┴────┬────────────┐
▼ ▼ ▼
┌───────┐ ┌───────┐ ┌──────────┐
│ Dev │ │Staging│ │Production│
└───────┘ └───────┘ └──────────┘
Представьте компанию, где используют отдельный репозиторий для production:
❌ Неправильно:
myapp-dev/ ← разработка здесь
myapp-staging/ ← тестирование здесь
myapp-prod/ ← production здесь (доступ только у сеньоров)
Проблемы такого подхода:
✅ Правильно:
myapp/ ← единый репозиторий
├── src/
├── tests/
├── requirements.txt
└── .github/workflows/ci.yml
Развёртывания:
- Dev: git checkout main && DEPLOY_ENV=dev ./deploy.sh
- Staging: git checkout main && DEPLOY_ENV=staging ./deploy.sh
- Prod: git checkout main && DEPLOY_ENV=prod ./deploy.sh
Преимущества:
Одно приложение — один репозиторий:
myapp/
├── src/
├── tests/
├── requirements.txt
└── README.md
Каждый микросервис — отдельная кодовая база:
user-service/ ← кодовая база сервиса пользователей
order-service/ ← кодовая база сервиса заказов
payment-service/ ← кодовая база сервиса платежей
Важно: у каждого сервиса своя независимая история версий и развёртываний.
company-apps/ ← единый репозиторий
├── user-service/
├── order-service/
├── payment-service/
└── shared-libs/
Это всё ещё соответствует 12-Factor, если:
Из одной кодовой базы развёртываются разные окружения:
| Окружение | Назначение | Конфигурация |
|---|---|---|
| Development | Локальная разработка | Локальная БД, debug-режим |
| Staging | Тестирование перед prod | Копия prod-данных, debug-режим |
| Production | Работа с реальными пользователями | Production-БД, debug отключён |
| CI/CD | Автоматические тесты | Временная БД, изолированное окружение |
# Один и тот же код, разные переменные окружения
git checkout main
# Развёртывание в dev
export DEPLOY_ENV=dev
export DATABASE_URL=postgres://localhost:5432/dev_db
export DEBUG=true
./deploy.sh
# Развёртывание в prod
export DEPLOY_ENV=prod
export DATABASE_URL=postgres://prod-db:5432/prod_db
export DEBUG=false
./deploy.shКод не меняется — меняется только конфигурация.
main (prod)
│
├─── release/v2.1 ───────► staging
│
├─── feature/new-payment
│
└─── hotfix/critical-bug
Процесс:
main после code reviewmain в stagingmain в production# Пометить релиз тегом
git tag -a v2.1.0 -m "Release version 2.1.0"
git push origin v2.1.0
# Развернуть конкретную версию
git checkout v2.1.0
./deploy.sh --env=prod# Ручное копирование файлов на сервер
scp app.py user@server:/var/www/
scp -r templates/ user@server:/var/www/templates/
ssh user@server "service apache restart"Проблемы:
# Неправильно: отдельные ветки для каждой среды
git checkout prod
# Код сильно отличается от main
# Фиксы из main не попадают в prod
git checkout staging
# Ещё одна версия кодаПроблемы:
# ❌ Неправильно: разные значения для разных сред в коде
if ENV == 'prod':
DATABASE_URL = 'postgres://prod-db/app'
elif ENV == 'staging':
DATABASE_URL = 'postgres://staging-db/app'
else:
DATABASE_URL = 'postgres://localhost/app'Правильно: конфигурация передаётся извне через переменные окружения.
# Инициализация репозитория
git init
git add .
git commit -m "Initial commit"
# Удалённый репозиторий
git remote add origin git@github.com:company/myapp.git
git push -u origin main# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to staging
run: ./deploy.sh staging
- name: Run tests
run: pytest
- name: Deploy to production
run: ./deploy.sh productionНастройте защиту ветки main:
main# Семантическое версионирование
git tag -a v2.1.0 -m "Release 2.1.0: new payment system"
git push origin v2.1.0
# Автоматическое создание релиза в GitHub/GitLab# Быстрый откат через git
git revert HEAD # Отмена последнего коммита
git push
# Или развёртывание предыдущего тега
git checkout v2.0.0
./deploy.sh --env=prod# Каждый сервис — отдельная кодовая база
github.com/company/user-service
github.com/company/order-service
github.com/company/payment-service
Преимущества:
# Все сервисы в одном репозитории
github.com/company/platform
├── services/
│ ├── user/
│ ├── order/
│ └── payment/
└── libs/
├── auth/
└── logging/
Преимущества:
| Задача | Инструменты |
|---|---|
| Контроль версий | Git, Mercurial, SVN |
| Хостинг репозиториев | GitHub, GitLab, Bitbucket |
| CI/CD | GitHub Actions, GitLab CI, Jenkins |
| Артефакты | Docker Hub, AWS ECR, Nexus |
Задайте себе вопросы:
# Компания использует FTP для деплоя
ls prod-files/
├── app.py ← изменён напрямую на сервере
├── utils.py ← версия 2.3
├── config.py ← содержит prod-пароли
└── templates/
└── index.html ← версия от вчера
Проблемы:
# Git репозиторий
git log --oneline
a1b2c3d (HEAD -> main, tag: v2.1.0) Add payment feature
e4f5g6h Fix login bug
i7j8k9l Initial commit
# Развёртывание
./deploy.sh production
# → Забирает код из Git
# → Собирает Docker-образ
# → Развёртывает в Kubernetes
Результат:
Ключевой вывод: Одна кодовая база — это источник истины для всего приложения. Из неё развёртываются все окружения, по ней отслеживается история изменений, к ней привязаны все процессы развёртывания и отката.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.