Files
image-gateway/docs/ci-cd.md
S.Gromov 98b162f2b8
Some checks failed
CI / e2e (push) Failing after 1m56s
CI / docker (push) Has been skipped
chore: добавить CI/CD для прод-деплоя
- добавлены Gitea workflows для CI и ручного CD

- настроен prod compose для запуска за reverse proxy

- добавлена публикация Caddy image в Container Registry

- обновлена документация по CI/CD и prod-сети
2026-05-04 12:51:28 +03:00

131 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CI/CD
Проект использует Gitea Actions workflows в `.gitea/workflows`.
## Прод Схема
В проде проект запускается через Docker Compose, а не через один общий Dockerfile.
Причины:
- `caddy` и `imgproxy` — разные runtime-сервисы;
- для Caddy нужен кастомный image с Souin, Otter и NutsDB modules;
- `imgproxy` берется как готовый upstream image `darthsim/imgproxy`;
- кешу нужны persistent volumes `caddy-data` и `caddy-cache`;
- Compose проще обновляет только Caddy image без пересборки на сервере;
- Image Gateway должен быть доступен только из сети внешнего reverse proxy.
В registry публикуется только кастомный Caddy image из `Dockerfile.caddy`. На сервере `docker-compose.yml` подставляет его через переменную `CADDY_IMAGE`.
Prod compose не публикует host-порты. Caddy подключается к external network `web` с alias `image-gateway`, поэтому внешний reverse proxy должен проксировать на `http://image-gateway:80` при `CADDY_PORT=80`.
## CI
Файл: `.gitea/workflows/ci.yml`.
Запускается на:
- push в `main`, `master`, `dev`;
- pull request в `main`, `master`, `dev`;
- ручной запуск через `workflow_dispatch`.
Что делает:
- проверяет `docker-compose.test.yml` через `docker compose config`;
- запускает e2e-тесты кеша через `./scripts/test-e2e.sh`;
- на основной ветке собирает и публикует Caddy image в Gitea Container Registry.
Публикуемые теги:
- branch tag, например `master` или `main`;
- commit SHA;
- `latest` для default branch.
## CD
Файл: `.gitea/workflows/deploy.yml`.
Запускается вручную через `workflow_dispatch`.
Что делает:
- вычисляет registry image текущего репозитория;
- подключается к серверу по SSH;
- копирует `docker-compose.yml` и `Caddyfile` в директорию деплоя;
- логинится в Gitea Container Registry;
- тянет `CADDY_IMAGE=<registry>/<repo>:latest`;
- создает Docker network внешнего reverse proxy, если ее еще нет;
- запускает `docker compose up -d --no-build`.
Сборка на прод-сервере не выполняется.
## Secrets
В Gitea repository secrets должны быть заданы:
| Secret | Назначение |
|---|---|
| `CR_USER` | пользователь Container Registry |
| `CR_TOKEN` | токен Container Registry |
| `SSH_PRIVATE_KEY` | приватный ключ для деплоя |
CD workflow использует те же registry и SSH secrets, что и другие проекты.
Настройки целевого сервера заданы в `env` файла `.gitea/workflows/deploy.yml`:
| Переменная | Значение по умолчанию | Назначение |
|---|---|---|
| `DEPLOY_HOST` | `188.225.47.78` | host/IP прод-сервера |
| `DEPLOY_USER` | `root` | SSH-пользователь |
| `DEPLOY_PATH` | `/opt/image-gateway` | директория проекта на сервере |
| `IMAGE_TAG` | `latest` | тег Caddy image для деплоя |
| `WEB_NETWORK` | `web` | Docker network внешнего reverse proxy |
На прод-сервере в `DEPLOY_PATH` должен лежать `.env` с runtime-настройками:
```env
DOMAIN=images.example.com
CADDY_PORT=80
WEB_NETWORK=web
IMGPROXY_KEY=
IMGPROXY_SALT=
IMGPROXY_ALLOWED_SOURCES=example.com,cdn.example.com
```
CD workflow не копирует `.env`, чтобы не перетирать секреты и runtime-настройки на сервере.
## Ручной Деплой На Сервере
Если нужно повторить деплой вручную на сервере:
```bash
cd /path/to/image-gateway
docker login registry.example.com
CADDY_IMAGE=registry.example.com/owner/image-gateway:latest docker compose -f docker-compose.yml pull caddy imgproxy
CADDY_IMAGE=registry.example.com/owner/image-gateway:latest docker compose -f docker-compose.yml up -d --no-build
```
## Reverse Proxy
Внешний reverse proxy должен быть подключен к той же Docker network, что и Image Gateway (`WEB_NETWORK`, по умолчанию `web`).
Внутренний upstream при `CADDY_PORT=80`:
```text
http://image-gateway:80
```
Прокидывайте исходный `Host`, чтобы Souin cache key не дробился по внутренним именам:
```text
Host: images.example.com
X-Forwarded-Proto: https
X-Forwarded-For: <client-ip>
```
Admin API `:2019` не должен публиковаться наружу.
## Skip CI
Для пропуска CI добавьте `[skip ci]` в сообщение коммита.