Files

4.7 KiB
Raw Permalink Blame History

Развёртывание Flamy Trade

Документ описывает production-развёртывание сайта trade.flamy.studio без ML-runtime и будущего API. Эти части подключаются отдельным этапом.

Схема

Internet
  -> Router :80/:443
  -> edge-proxy VM / Caddy
  -> 10.20.0.20:18082
  -> flamy_trade-nginx-1
  -> flamy_trade-app-1:3000

Compose project name зафиксирован как flamy_trade. container_name не задаётся, чтобы не ломать стандартное управление Compose.

Переменные

Скопируйте .env.example в .env на сервере и проверьте значения:

PUBLIC_SITE_URL=https://trade.flamy.studio
PUBLIC_SITE_NAME=Flamy Trade
PUBLIC_SITE_DESCRIPTION=Публичная витрина ML-прогнозов для крипторынка.
PUBLIC_DASHBOARD_DATA_MODE=research-static

HOST=0.0.0.0
PORT=3000
ORIGIN=https://trade.flamy.studio
BODY_SIZE_LIMIT=1M
SHUTDOWN_TIMEOUT=15
APP_STOP_GRACE_PERIOD=20s

APP_IMAGE_REPOSITORY=registry.example.com/flamy-trade
APP_IMAGE_TAG=<git-sha>
BUILD_DATE=<utc-iso-date>
VCS_REF=<git-sha>

APP_HOST_IP=10.20.0.20
APP_PUBLISHED_PORT=18082
NGINX_IMAGE=nginxinc/nginx-unprivileged:1.30.4-alpine-perl@sha256:36fa38fb8f34faba45e7e1857644d6561f2faf45e7ce6b15e97d1a2a1682a0cd

Перед фиксацией порта проверьте, что 18082 свободен:

sudo ss -lntup | grep ':18082'
docker ps --format 'table {{.Names}}\t{{.Ports}}'

Проверки перед сборкой

pnpm install --frozen-lockfile
pnpm format:check
pnpm lint
pnpm check
pnpm build
pnpm audit
docker compose config

Сборка

Перед сборкой image задайте provenance:

export BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
export VCS_REF="$(git rev-parse HEAD)"
export APP_IMAGE_TAG="$VCS_REF"

Сборка и запуск:

docker compose build --pull
docker compose up -d --wait
docker compose ps
docker compose logs --tail=200

Caddy

Блок для edge-proxy:

trade.flamy.studio {
        encode zstd gzip

        reverse_proxy 10.20.0.20:18082 {
                header_up Host {host}
                header_up X-Real-IP {remote_host}
                header_up X-Forwarded-For {remote_host}
                header_up X-Forwarded-Proto {scheme}
        }
}

Перед reload:

sudo cp -a /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak.$(date +%F_%H%M%S)
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

Smoke-check

С Docker-runtime:

curl -fsS http://10.20.0.20:18082/healthz
curl -fsSI http://10.20.0.20:18082/
curl -fsSI http://10.20.0.20:18082/robots.txt
curl -fsSI http://10.20.0.20:18082/sitemap.xml

Снаружи:

curl -fsSI https://trade.flamy.studio/
curl -fsS https://trade.flamy.studio/healthz
curl -fsS https://trade.flamy.studio/robots.txt
curl -fsS https://trade.flamy.studio/sitemap.xml

Маршруты:

/                                  200
/about                             200
/blog                              200
/blog/osnovy-upravleniya-riskami   200
/dashboard                         200
/healthz                           200
/favicon.svg                       200
/robots.txt                        200
/sitemap.xml                       200
/nesuschestvuyuschiy-url           404

Проверка headers:

curl -fsSI https://trade.flamy.studio/
curl -fsSI https://trade.flamy.studio/favicon.svg
curl -fsSI https://trade.flamy.studio/_app/immutable/<real-file>.js

Ожидаемо:

X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: SAMEORIGIN
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

Content-Security-Policy задаётся SvelteKit и ожидается на HTML-ответах приложения.

Для /_app/immutable/* ожидается:

Cache-Control: public, max-age=31536000, immutable

Для HTML:

Cache-Control: no-cache

Rollback

Надёжный rollback должен опираться на immutable image tag:

${APP_IMAGE_REPOSITORY}:<git-sha>

На production-сервере меняется только APP_IMAGE_TAG, затем выполняется:

docker compose pull app
docker compose up -d --no-build --wait

Если проблема в маршрутизации, восстановите backup Caddyfile и выполните:

sudo systemctl reload caddy

Предыдущий image не удаляется до успешного smoke-check нового релиза.