Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Build, Release, Run — разделение стадий
build_release_run

Build, Release, Run — разделение стадий

Строгое разделение на сборку, релиз и запуск приложения

Build, Release, Run: Разделение стадий

Строго разделяйте стадии сборки, релиза и запуска

#Суть принципа

Build, Release, Run — пятый фактор 12-Factor App. Принцип гласит:

Жизненный цикл приложения должен быть строго разделён на три стадии:

  • Build — сборка артефакта из кода
  • Release — объединение артефакта с конфигурацией
  • Run — запуск процесса приложения
┌─────────────┐    ┌──────────────┐    ┌─────────────┐
│    BUILD    │ →  │    RELEASE   │ →  │     RUN     │
│             │    │              │    │             │
│ Компиляция  │    │ Артефакт +   │    │ Запуск      │
│ Зависимости │    │ Конфигурация │    │ процесса    │
│ Тесты       │    │              │    │             │
└─────────────┘    └──────────────┘    └─────────────┘
     ↓                    ↓                   ↓
  Артефакт            Релиз              Процесс
 (код + deps)      (артефакт + config)  (исполнение)

#Три стадии жизненного цикла

#1. Build (Сборка)

Что происходит:

  • Компиляция кода (если требуется)
  • Установка зависимостей
  • Запуск тестов
  • Создание артефакта

Вход: исходный код из репозитория

Выход: артефакт (бинарный файл, Docker-образ, JAR-файл)

Примеры:

# Python: установка зависимостей pip install -r requirements.txt # Артефакт: исходный код + установленные пакеты # Node.js: установка зависимостей и сборка npm install npm run build # Артефакт: файлы в dist/ + node_modules # Go: компиляция go build -o myapp # Артефакт: бинарный файл myapp # Docker: сборка образа docker build -t myapp:latest . # Артефакт: Docker-образ

#2. Release (Релиз)

Что происходит:

  • Объединение артефакта с конфигурацией окружения
  • Создание версии, готовой к запуску

Вход: артефакт + конфигурация (переменные окружения)

Выход: релиз (готовая к запуску версия)

Пример:

# Артефакт: Docker-образ myapp:latest # Конфигурация: # - DATABASE_URL=postgres://prod-db/app # - SECRET_KEY=prod-secret # - DEBUG=false # Релиз: контейнер с применённой конфигурацией docker run -d \ -e DATABASE_URL=postgres://prod-db/app \ -e SECRET_KEY=prod-secret \ -e DEBUG=false \ myapp:latest

Важно: один и тот же артефакт может быть использован для разных релизов:

# Один артефакт (Docker-образ), разные релизы: # Staging релиз docker run -e DATABASE_URL=postgres://staging-db/app myapp:latest # Production релиз docker run -e DATABASE_URL=postgres://prod-db/app myapp:latest

#3. Run (Запуск)

Что происходит:

  • Запуск процесса приложения
  • Обработка запросов пользователей

Вход: релиз (артефакт + конфигурация)

Выход: работающее приложение

Пример:

# Запуск процесса python app.py gunicorn app:app docker start container_id kubectl apply -f deployment.yaml

Важно: на стадии Run код и конфигурация неизменны. Для изменений требуется новый Release.

#Почему разделение важно?

#Проблема: смешанные стадии

# ❌ Неправильно: сборка при запуске #!/bin/bash # run.sh # Установка зависимостей при каждом запуске pip install -r requirements.txt # Миграции БД при запуске python manage.py migrate # Сборка статики при запуске npm run build # Запуск приложения python app.py

Проблемы:

  1. Непредсказуемость — каждый запуск может дать разный результат
  2. Медленный старт — установка зависимостей занимает время
  3. Невозможность отката — нельзя вернуться к предыдущей версии
  4. Конфликты — одновременные запуски могут мешать друг другу

#Решение: явное разделение

# ✅ BUILD (сборка артефакта) docker build -t myapp:abc123 . # ✅ RELEASE (создание релиза) # Релиз = образ myapp:abc123 + конфигурация # ✅ RUN (запуск) docker run -d myapp:abc123

Преимущества:

  • ✅ Воспроизводимость — артефакт одинаковый для всех сред
  • ✅ Быстрый старт — запуск занимает секунды
  • ✅ Откат — можно запустить предыдущий артефакт
  • ✅ Аудит — известно, какой артефакт где работает

#Артефакты и версионирование

#Что такое артефакт?

Артефакт — это результат стадии Build:

ЯзыкАртефакт
PythonИсходный код + установленные пакеты
Node.jsФайлы в dist/ + node_modules
GoБинарный файл
JavaJAR/WAR файл
ЛюбойDocker-образ

#Версионирование артефактов

# Семантическое версионирование docker build -t myapp:1.0.0 . docker build -t myapp:1.1.0 . docker build -t myapp:2.0.0 . # Git-коммиты как версии docker build -t myapp:abc123 . # Короткий хэш коммита docker build -t myapp:abc123def456 . # Временные метки docker build -t myapp:2024-01-15-10-30-00 .

#Хранение артефактов

# Docker Registry docker push registry.example.com/myapp:1.0.0 # AWS ECR docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:1.0.0 # GitHub Packages docker push ghcr.io/username/myapp:1.0.0 # Nexus, Artifactory mvn deploy # Для Java

#CI/CD пайплайн

#Пример: GitHub Actions

# .github/workflows/deploy.yml name: Build, Release, Deploy on: push: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build Docker image run: docker build -t myapp:${{ github.sha }} . - name: Run tests run: docker run myapp:${{ github.sha }} pytest - name: Push to registry run: | docker tag myapp:${{ github.sha }} registry.example.com/myapp:${{ github.sha }} docker push registry.example.com/myapp:${{ github.sha }} release: needs: build runs-on: ubuntu-latest steps: - name: Deploy to staging run: | kubectl set image deployment/myapp \ myapp=registry.example.com/myapp:${{ github.sha }} \ --namespace=staging - name: Run integration tests run: ./run-integration-tests.sh - name: Deploy to production run: | kubectl set image deployment/myapp \ myapp=registry.example.com/myapp:${{ github.sha }} \ --namespace=production run: needs: release runs-on: ubuntu-latest steps: - name: Health check run: | curl -f https://api.example.com/health || exit 1

#Визуализация пайплайна

┌─────────────────────────────────────────────────────────┐
│                    GitHub Push                          │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  BUILD: docker build, test, push to registry            │
│  Артефакт: myapp:abc123                                 │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  RELEASE: kubectl set image (staging)                   │
│  Релиз: myapp:abc123 + staging-config                   │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  Integration Tests                                      │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  RELEASE: kubectl set image (production)                │
│  Релиз: myapp:abc123 + production-config                │
└────────────────────┬────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────┐
│  RUN: приложение обрабатывает запросы                   │
│  Health checks, monitoring                              │
└─────────────────────────────────────────────────────────┘

#Откат релиза

#Проблема: нужно срочно откатить изменения

# ❌ Неправильно: откат через изменение кода git revert HEAD git push # Ждать 30 минут, пока CI/CD соберёт новый артефакт

#Решение: откат через запуск предыдущего артефакта

# ✅ Правильно: запуск предыдущего артефакта kubectl set image deployment/myapp myapp=registry.example.com/myapp:prev-commit # Или через Docker docker stop myapp docker run -d registry.example.com/myapp:prev-commit

Преимущества:

  • Откат за секунды, а не минуты
  • Не требует сборки нового артефакта
  • Предыдущий артефакт уже протестирован

#Антипаттерны

#❌ Сборка при запуске

# ❌ Неправильно: Dockerfile FROM python:3.12 COPY . /app WORKDIR /app # Сборка при каждом запуске контейнера! CMD pip install -r requirements.txt && python app.py

Проблема: каждый запуск контейнера устанавливает зависимости заново.

Правильно:

# ✅ Правильно: сборка на стадии Build FROM python:3.12 WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt # Сборка COPY . . CMD ["python", "app.py"] # Только запуск

#❌ Миграции БД при запуске

# ❌ Неправильно: app.py from flask import Flask import subprocess app = Flask(__name__) # Миграции при каждом запуске! subprocess.run(['python', 'manage.py', 'migrate']) @app.route('/') def index(): return 'Hello'

Проблема: миграции должны выполняться на стадии Release, а не Run.

Правильно:

# CI/CD пайплайн: # 1. Build docker build -t myapp:latest . # 2. Release (миграции перед запуском) kubectl run migration --image=myapp:latest -- python manage.py migrate # 3. Run kubectl set image deployment/myapp myapp=myapp:latest

#❌ Изменение кода в production

# ❌ Неправильно: прямое редактирование на сервере ssh user@server vim /var/www/app.py systemctl restart myapp

Проблема: изменения не отслеживаются, невозможно воспроизвести.

Правильно:

# Изменение кода → новый Build → новый Release git commit -m "Fix bug" git push # CI/CD автоматически соберёт и развернёт новый артефакт

#❌ Ручное копирование артефактов

# ❌ Неправильно: SCP на сервер scp app.py user@server:/var/www/ scp -r node_modules/ user@server:/var/www/

Проблема: нет версионирования, невозможно откатиться.

Правильно:

# Использование registry docker build -t myapp:1.0.0 . docker push registry.example.com/myapp:1.0.0 # Развёртывание из registry kubectl set image deployment/myapp myapp=registry.example.com/myapp:1.0.0

#Build, Release, Run в разных средах

#Development

# BUILD docker build -t myapp:dev . # RELEASE (локальная конфигурация) docker run -d \ -e DATABASE_URL=postgres://localhost/dev \ -e DEBUG=true \ myapp:dev # RUN # Приложение запущено, обработка запросов

#Staging

# BUILD (тот же артефакт) docker build -t myapp:abc123 . docker push registry.example.com/myapp:abc123 # RELEASE (staging конфигурация) kubectl set image deployment/myapp \ myapp=registry.example.com/myapp:abc123 \ --namespace=staging # RUN # Staging окружение доступно для тестирования

#Production

# BUILD (тот же артефакт) # myapp:abc123 уже в registry # RELEASE (production конфигурация) kubectl set image deployment/myapp \ myapp=registry.example.com/myapp:abc123 \ --namespace=production # RUN # Production окружение обрабатывает запросы пользователей

#Инструменты

СтадияИнструменты
BuildDocker, Maven, Gradle, npm, pip, go build
ReleaseKubernetes, Docker Compose, ECS, Heroku
Runsystemd, supervisord, Kubernetes, Docker
CI/CDGitHub Actions, GitLab CI, Jenkins, ArgoCD
RegistryDocker Hub, AWS ECR, GitHub Packages, Nexus

#Проверка соответствия принципу

Задайте себе вопросы:

  • Разделены ли явно стадии Build, Release, Run?
  • Можно ли запустить предыдущую версию артефакта?
  • Сборка происходит только на стадии Build?
  • Миграции БД выполняются на стадии Release?
  • Запуск приложения не включает установку зависимостей?
  • Артефакты версионируются и хранятся в registry?

#Связь с другими факторами

  • Codebase — артефакт собирается из одной кодовой базы
  • Dependencies — установка зависимостей на стадии Build
  • Config — конфигурация добавляется на стадии Release
  • Processes — стадия Run запускает процессы приложения

#Пример из практики

#До: хаос со сборкой

# ❌ Скрипт развёртывания #!/bin/bash cd /var/www/app # Сборка при развёртывании git pull npm install npm run build python manage.py migrate # Перезапуск systemctl restart myapp

Проблемы:

  • Невозможно откатиться
  • Сборка занимает 10 минут
  • Разные версии на разных серверах

#После: явное разделение

# ✅ BUILD (CI/CD) docker build -t myapp:abc123 . docker push registry.example.com/myapp:abc123 # ✅ RELEASE kubectl set image deployment/myapp myapp=registry.example.com/myapp:abc123 # ✅ RUN # Приложение запущено за секунды

Результат:

  • Развёртывание за 30 секунд
  • Откат одной командой
  • Одинаковые артефакты на всех серверах

Ключевой вывод: Строгое разделение на Build, Release, Run обеспечивает воспроизводимость, быстрый откат и предсказуемость развёртываний. Артефакт собирается один раз и используется для всех сред.

Далее: Processes — stateless процессы