# Дополнение к ТЗ: Инфраструктура, CI/CD и развертывание --- ## 1. Архитектура развертывания Развертывание системы осуществляется в контейнеризованной среде с использованием **Docker Compose**. Это обеспечивает простоту управления зависимостями (БД, кэш) и изоляцию компонентов приложения. ### 1.1 Компоненты Docker Compose Среда развертывания включает следующие сервисы: 1. **API Service (Go)** — основной HTTP-сервер. 2. **Cron Service (Go)** — фоновые задачи (обновление справочников, проверка статуса). *Может быть объединен с API в один бинарник/контейнер, если используется встроенный планировщик, но рекомендуется запускать отдельным процессом.* 3. **PostgreSQL** — база данных со справочниками и маршрутами (используется официальный образ, данные хранятся в Docker Volumes). 4. **Redis** — кэш-слой для API Яндекс.Расписаний. 5. **Watchtower** — сервис для автоматического обновления контейнеров. ### 1.2 Использование Watchtower Для реализации автоматического деплоя (CD) на сервере разворачивается образ `nickfedor/watchtower`. Он регулярно опрашивает Docker Registry (или ожидает webhook) и, при появлении нового образа приложения с тегом `latest` (или другим заданным), автоматически скачивает его, корректно останавливает старый контейнер и запускает новый с теми же параметрами окружения. --- ## 2. Процесс CI/CD (Gitea Actions) Весь процесс непрерывной интеграции и доставки управляется встроенным механизмом **Gitea Actions** и запускается автоматически при любом `push` в ветку `master`. ### 2.1 Этапы пайплайна (Pipeline Steps) Пайплайн описывается в файле `.gitea/workflows/deploy.yml` и включает следующие шаги: 1. **Checkout**: Клонирование актуального кода из ветки `master`. 2. **Setup Go**: Установка необходимой версии Go и настройка кэширования модулей (`go mod download`). 3. **Lint & Test**: - Запуск линтеров (например, `golangci-lint`) для проверки качества кода. - Запуск unit-тестов (`go test -v ./...`), включая тесты графа маршрутизации с моками вместо реального API. 4. **Build Binaries**: Компиляция исполняемых файлов для Linux/amd64 (API и Cron). 5. **Docker Build & Push**: - Сборка Docker-образа приложения на основе `Dockerfile` (рекомендуется multi-stage сборка для уменьшения веса финального образа). - Авторизация в приватном или публичном Docker Registry. - Пуш собранного образа с тегами `latest` и `{{.CommitID}}`. ### 2.2 Схема автоматического деплоя (CD) 1. Разработчик делает `git push origin master`. 2. Gitea Actions успешно прогоняет тесты и пушит образ `my-registry.com/travel-api:latest`. 3. На production-сервере `nickfedor/watchtower` замечает обновление образа. 4. Watchtower выполняет pull нового образа и перезапускает сервисы приложения без ручного вмешательства. --- ## 3. Примеры конфигурации ### 3.1 Пример `docker-compose.yml` (Production) ```yaml version: '3.8' services: travel-api: image: my-registry.com/travel-api:latest restart: always ports: - "8080:8080" environment: - DB_DSN=postgres://user:pass@db:5432/travel?sslmode=disable - REDIS_ADDR=redis:6379 - YANDEX_API_KEY=${YANDEX_API_KEY} depends_on: - db - redis db: image: postgres:15-alpine restart: always environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=travel volumes: - pg_data:/var/lib/postgresql/data redis: image: redis:7-alpine restart: always volumes: - redis_data:/data watchtower: image: nickfedor/watchtower restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock # Если используется приватный реестр, прокидываем авторизацию: # - /root/.docker/config.json:/config.json:ro command: --interval 60 --cleanup travel-api # Обновляем только контейнер travel-api, проверяя изменения каждые 60 секунд (или по крону) volumes: pg_data: redis_data: ``` ### 3.2 Пример Gitea Actions (`.gitea/workflows/deploy.yml`) ```yaml name: Build, Test and Publish on: push: branches: - master jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v3 - name: Set up Go uses: actions/setup-go@v4 with: go-version: '1.22' - name: Go Modules Cache uses: actions/cache@v3 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- - name: Run Tests run: go test -v -race ./... - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to Docker Registry uses: docker/login-action@v2 with: registry: my-registry.com username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and Push Docker Image uses: docker/build-push-action@v4 with: context: . push: true tags: my-registry.com/travel-api:latest,my-registry.com/travel-api:${{ gitea.sha }} ``` ## 4. Рекомендации по безопасности и отказоустойчивости 1. **Секреты:** Ключи API Яндекс.Расписаний, пароли от БД и доступы к Registry не должны храниться в коде. В Gitea Actions они зашиваются через механизм *Secrets*, а в Docker Compose — через файл `.env` на сервере. 2. **Откаты (Rollback):** Если новая версия `latest` ломает production, откатить версию можно путем изменения тега в `docker-compose.yml` на предыдущий успешный коммит-хэш (например, `image: my-registry.com/travel-api:a1b2c3d`) и ручного перезапуска, либо через revert коммита в `master` (что триггернет Gitea Actions на сборку "исправленного" `latest`). 3. **Downtime:** При базовой настройке Watchtower будет небольшой даунтайм в несколько секунд во время перезапуска контейнера. Для MVP/версии 1.0 это приемлемо. Для zero-downtime в будущем потребуется переход на Docker Swarm / Kubernetes или поднятие прокси (nginx/traefik) с health-чеками и blue/green деплоем.