16. DevOps workflow¶
Довідник бонус-уроку «Linux для розробника»
Розділ перевірено: кожну команду виконано в контейнерах Ubuntu, Debian і python:3.12-slim. Урок з вправами — Бонус. Linux.
Навіщо це потрібно¶
Ти написав код. Натиснув git push. Через 5 хвилин зміни вже на production — автоматично. Без ручного SSH, без копіювання файлів, без "я щойно задеплоїв, перевіряйте". Це і є DevOps workflow.
Що таке DevOps¶
DevOps — це не посада і не набір інструментів. Це культура і набір практик, які допомагають командам швидко і безпечно доставляти зміни від ноутбука розробника до production-сервера.
DevOps = Development + Operations.
Раніше: розробники писали код, а окрема команда (operations) деплоїла і підтримувала. Між ними — "стіна" і постійні конфлікти.
Сьогодні: команди разом відповідають за весь шлях коду — від написання до моніторингу в production.
Ключові концепції¶
| Концепція | Що означає |
|---|---|
| CI (Continuous Integration) | Автоматична перевірка коду при кожному push |
| CD (Continuous Delivery) | Автоматична підготовка до деплою |
| CD (Continuous Deployment) | Автоматичний деплой на production |
| Pipeline | Послідовність кроків від коду до production |
| Staging | Тестовий сервер, що імітує production |
| Production | Реальний сервер для кінцевих користувачів |
| Rollback | Відкат до попередньої робочої версії |
| IaC | Infrastructure as Code — сервери описані як код |
Шлях коду від ноутбука до production¶
flowchart LR
classDef step fill:#eceff1,stroke:#546e7a,stroke-width:1px,color:#1a1a1a;
classDef decision fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#1a1a1a;
classDef success fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px,color:#1a1a1a;
classDef error fill:#ffebee,stroke:#c62828,stroke-width:3px,color:#1a1a1a;
classDef warning fill:#fff8e1,stroke:#e65100,stroke-width:2px,color:#1a1a1a;
Dev["1. Розробник<br>пише код"] --> Push["2. git push<br>на GitHub"]
Push --> CI{"3. CI:<br>тести + лінтер"}
CI -->|"провалились"| Notify["Сповіщення<br>розробнику"]
CI -->|"пройшли"| Build["4. Build:<br>docker build"]
Build --> Registry["5. Push image<br>до Registry"]
Registry --> Staging["6. Deploy<br>на Staging"]
Staging --> ManualQA{"Ручне QA<br>(або auto E2E)"}
ManualQA -->|"OK"| Production["7. Deploy<br>на Production"]
Production --> Monitor["8. Monitoring<br>логи, метрики"]
Monitor -->|"є проблеми"| Rollback["Rollback<br>до попередньої версії"]
Monitor --> Dev
class Dev,Push,Build,Registry,Staging,Monitor step
class CI,ManualQA decision
class Notify error
class Production success
class Rollback warning
CI — Continuous Integration¶
CI автоматично запускається при кожному push в репозиторій і виконує:
ruff check .— лінтерpytest— тести- Можливо:
pip-audit— перевірка вразливостей у залежностях
Якщо щось провалилося — pull request не можна змерджити (коли для main увімкнено branch protection з обов'язковими перевірками). Код з поламаними тестами не потрапить у main.
GitHub Actions — приклад CI для Django¶
# .github/workflows/ci.yml
name: Django CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
services:
db:
image: postgres:16
env:
POSTGRES_DB: test_db
POSTGRES_USER: test_user
POSTGRES_PASSWORD: test_pass
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run linter
run: ruff check .
- name: Run tests
env:
DATABASE_URL: postgres://test_user:test_pass@localhost:5432/test_db
DEBUG: "True"
SECRET_KEY: "ci-test-secret-key"
run: pytest --tb=short
CD — Continuous Deployment¶
Після успішного CI — автоматичний деплой:
# .github/workflows/ci.yml — ще один job після test
# (needs бачить лише jobs того самого workflow-файлу)
deploy:
needs: test # тільки якщо тести пройшли
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to server
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/myapp
git pull origin main
source .venv/bin/activate
pip install -r requirements.txt
python manage.py migrate --noinput
python manage.py collectstatic --noinput
sudo systemctl restart myapp
Staging і Production¶
Staging — це дзеркало production. Ти деплоїш туди спочатку, перевіряєш що все працює, і тільки потім — на production.
На staging: - Реальна база (копія або тест-дані) - Реальний Docker, Nginx, Gunicorn - Але доступ обмежений (не публічний)
Переваги: - Баги знаходяться до того як побачать користувачі - Можна протестувати міграції - Команда QA може перевірити нові фічі
Rollback¶
Якщо після деплою щось зламалося — треба швидко повернутися назад.
Варіант 1: Git rollback¶
git log --oneline -5 # знайти попередній коміт
git checkout HEAD~1 # або конкретний SHA
sudo systemctl restart myapp
Варіант 2: Docker image tags¶
# Попередній image ще в registry;
# у docker-compose.yml: image: myapp:${TAG:-latest}
TAG=v1.2.3 docker compose up -d # з попередньою версією
Варіант 3: Через CI/CD¶
Більшість CI/CD систем мають кнопку "Redeploy previous build".
Infrastructure as Code (IaC)¶
Якщо конфігурацію сервера описати в коді — її можна версіонувати, відтворити, переглянути зміни, і розгорнути знову після катастрофи.
Замість того щоб вручну налаштовувати Nginx, PostgreSQL, firewall — це описується в файлах (Terraform, Ansible, Pulumi) і запускається автоматично.
Для початківця: достатньо docker-compose.yml і Bash-скриптів. Terraform і Ansible — наступний рівень.
Типові помилки початківців¶
Помилка 1: Деплоїти вручну без скрипта
Одного разу забудеш
collectstaticабоmigrateі сайт зламається.
Помилка 2: Деплоїти без тестів
Без CI тести не запускаються автоматично і баги потрапляють на production.
Помилка 3: Немає staging
Перший раз бачиш поведінку на production. Немає можливості відтворити проблему.
Практичне завдання¶
Завдання 1¶
Намалюй pipeline для свого Django-проєкту: від git push до живого сайту. Які кроки? Що автоматично, що вручну?
Завдання 2¶
Додай .github/workflows/ci.yml у свій проєкт з кроками: install, ruff, pytest. Перевір що він запускається при push.
Завдання 3¶
Напиши deploy.sh — скрипт деплою на сервер, який виконує git pull, migrate, collectstatic, restart.
Самоперевірка¶
- [ ] Я можу пояснити що таке CI/CD
- [ ] Я розумію навіщо потрібен Staging
- [ ] Я знаю, що таке rollback і як його зробити
- [ ] Я можу написати базовий GitHub Actions workflow для Django
- [ ] Я розумію шлях коду від push до production
Короткий підсумок¶
DevOps — практики для швидкої і безпечної доставки коду. CI перевіряє тести при кожному push. CD автоматизує деплой. Staging — безпечне місце для тестування перед production. Rollback — план відступу. Наступний крок — Kubernetes overview.