Введение
Разработка на Python — это не только написание чистого кода, но и постоянная борьба с рутиной: запустить тесты, собрать приложение, задеплоить на сервер. Каждый раз делать это вручную — терять время и рисковать ошибками. CI/CD (Continuous Integration / Continuous Delivery — непрерывная интеграция и доставка) решает эту проблему раз и навсегда. Связка GitHub Actions и Docker позволяет автоматизировать весь процесс: от пуша в репозиторий до запуска контейнера в продакшене. В этой статье я, как практикующий DevOps-инженер, покажу, как настроить пайплайн для типового бэкенда на FastAPI. Мы разберём конфигурации, лучшие практики и типичные ошибки — без воды, только код и реальный опыт.
Что такое CI/CD и зачем это Python-разработчику?
CI/CD — это методология, которая превращает разрозненные шаги (линтер, тесты, сборка, деплой) в единый автоматический конвейер. Для Python-проекта это особенно актуально: вы можете мгновенно проверять, не сломал ли новый коммит существующую логику, и доставлять обновления пользователям за минуты. GitHub Actions — это бесплатный встроенный инструмент GitHub, который запускает ваши скрипты в ответ на события (push, pull request). Docker же упаковывает приложение со всеми зависимостями, гарантируя, что оно будет работать одинаково на вашем ноутбуке, тестовом сервере и в облаке AWS.
Пошаговое руководство: от репозитория до продакшена
Шаг 1. Подготовка Python-проекта на FastAPI
Допустим, у нас есть простое FastAPI-приложение с одним эндпоинтом. Структура файлов:
my-python-app/
├── app/
│ ├── __init__.py
│ └── main.py
├── requirements.txt
├── Dockerfile
├── .github/
│ └── workflows/
│ └── ci-cd.yml
└── tests/
└── test_main.py
Содержимое app/main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello, DevOps!"}
Файл requirements.txt:
fastapi==0.111.0
uvicorn==0.30.1
pytest==8.2.0
Шаг 2. Создаём Dockerfile
Dockerfile — это рецепт сборки образа. Для Python используем официальный лёгкий образ python:3.12-slim:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Шаг 3. Настраиваем GitHub Actions для CI (тестирование и линтинг)
Создаём файл .github/workflows/ci-cd.yml. Начнём с этапа непрерывной интеграции (CI):
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
run: |
pytest
Этот пайплайн запускается при каждом пуше в main или создании pull request. Он устанавливает зависимости и прогоняет тесты. Если тесты падают — деплой не произойдёт.
Шаг 4. Добавляем сборку и пуш Docker-образа (CD)
Теперь добавим этап доставки (CD). Для этого нам понадобится Docker Hub (или GitHub Container Registry). Создаём секреты в репозитории: Settings > Secrets and variables > Actions — добавляем DOCKER_USERNAME и DOCKER_PASSWORD.
Расширяем ci-cd.yml:
build-and-push:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/my-python-app:latest
Шаг 5. Автоматический деплой на AWS EC2
Для полной автоматизации добавим деплой на виртуальную машину (например, AWS EC2). Используем SSH:
deploy:
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: Deploy to EC2
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USER }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
docker pull ${{ secrets.DOCKER_USERNAME }}/my-python-app:latest
docker stop my-app || true
docker rm my-app || true
docker run -d --name my-app -p 80:8000 ${{ secrets.DOCKER_USERNAME }}/my-python-app:latest
Этот шаг подключается к EC2, скачивает свежий образ и перезапускает контейнер. В реальном проекте стоит добавить health-чеки и откат при ошибке.
Таблица: сравнение этапов CI/CD
| Этап | Инструмент | Действие | Критичность |
|---|---|---|---|
| Тестирование | GitHub Actions (pytest) | Запуск unit-тестов | Высокая — ловит баги до сборки |
| Сборка образа | Docker + GitHub Actions | Создание контейнера | Средняя — упаковывает код |
| Пуш в registry | Docker Hub | Хранение версий | Средняя — нужен для деплоя |
| Деплой на сервер | SSH + Docker | Запуск контейнера | Высокая — доставляет фичи |
Типичные ошибки и как их избежать
- Секреты в коде: Никогда не храните пароли или ключи в YAML-файлах. Используйте
secretsGitHub. Если секрет утёк — немедленно отзовите его. - Тяжёлые образы: Используйте slim-версии Python и многослойную сборку (multi-stage builds) — это ускоряет деплой.
- Отсутствие тестов: Если тесты не написаны, CI/CD теряет смысл. Хотя бы один тест должен быть.
- Игнорирование кэширования: GitHub Actions кэширует зависимости через
actions/cache, что сокращает время пайплайна в 2-3 раза.
LSI-слова и практические рекомендации
В контексте CI/CD для Python важно учитывать следующие связанные термины (LSI):
- контейнеризация — основа Docker, позволяет изолировать окружение;
- оркестрация — управление несколькими контейнерами (например, Kubernetes);
- мониторинг — наблюдение за запущенным приложением (Prometheus + Grafana);
- инфраструктура как код (IaC) — описание серверов через Terraform или Ansible;
- логирование — сбор логов для отладки (ELK-стек);
- безопасность контейнеров — сканирование образов на уязвимости (Trivy);
- автоматизация деплоя — ключевая цель всего пайплайна.
Рекомендую добавить в пайплайн шаг сканирования безопасности Docker-образа — это защитит от известных CVE. Например, используйте aquasecurity/trivy-action.
Заключение
Вы только что настроили полноценный CI/CD пайплайн для Python-проекта: от тестирования до деплоя на AWS EC2. GitHub Actions и Docker — это мощный дуэт, который экономит часы ручной работы и снижает риск человеческой ошибки. Теперь ваш код проходит проверку автоматически, а пользователи получают обновления быстрее. Если вы хотите углубиться в тему и научиться управлять инфраструктурой на уровне профессионала — изучайте Kubernetes, Terraform и мониторинг. Начните с малого: добавьте кэширование зависимостей в свой workflow и посмотрите, как ускорится сборка. Удачи в автоматизации!
Комментарии