docs(deploy-memory): refonte split web/api 2 services
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
dd93249362
commit
985e817289
@ -30,18 +30,43 @@ Push git, le CI build + rollout auto (filter sur `landing/**`, `Dockerfile`,
|
||||
|
||||
## 2. App SaaS (`app.rubis.arthurbarre.fr`)
|
||||
|
||||
### Infra
|
||||
- Deployment : `rubis-app` · Container : `app` · NodePort : `30110`
|
||||
**Architecture en 2 services** : nginx en frontal (web) + API Node interne.
|
||||
|
||||
```
|
||||
Traefik :443 → app.rubis.arthurbarre.fr:30110 → rubis-web (nginx)
|
||||
├─ / → SPA static (try_files)
|
||||
└─ /api/* → rubis-api (ClusterIP :3333)
|
||||
```
|
||||
|
||||
### rubis-web — frontend (NodePort 30110, exposé)
|
||||
- Image : `git.arthurbarre.fr/ordinarthur/rubis-web`
|
||||
- Container : `web` (nginx-alpine + SPA Vite dist)
|
||||
- Sert /assets/* (cache 1y immutable), / (SPA fallback try_files)
|
||||
- Reverse-proxy /api/* → rubis-api.rubis.svc.cluster.local:3333
|
||||
- Manifest : `k3s/app/web.yml`
|
||||
- Workflow CI : `.gitea/workflows/deploy-web.yml`
|
||||
- Source : `apps/web`, `packages/shared` + `apps/web/nginx.conf`
|
||||
|
||||
### rubis-api — backend (ClusterIP, interne uniquement)
|
||||
- Image : `git.arthurbarre.fr/ordinarthur/rubis-api`
|
||||
- Container : `api` (Node 22 + AdonisJS V7)
|
||||
- Workers BullMQ dans le même process (cf. `start/queue.ts`)
|
||||
- Init container `migrate` : `node ace.js migration:run --force` depuis
|
||||
`/app/apps/api/build` (idempotent)
|
||||
- Sidecar Redis : Deployment `rubis-redis` (ClusterIP, PVC 1Gi local-path,
|
||||
backend BullMQ + cache)
|
||||
- Image : `git.arthurbarre.fr/ordinarthur/rubis-app`
|
||||
- Domaine : https://app.rubis.arthurbarre.fr
|
||||
- Manifests : `k3s/app/{deployment.yml,service.yml,redis.yml}`
|
||||
- Probes K3s sur `/api/v1/health`
|
||||
- Manifest : `k3s/app/api.yml` (Deployment + Service ClusterIP + ConfigMap)
|
||||
- Workflow CI : `.gitea/workflows/deploy-api.yml`
|
||||
- Source : `apps/api`, `packages/shared`
|
||||
|
||||
### rubis-redis — backend BullMQ + cache (ClusterIP)
|
||||
- Image : `redis:7.4-alpine`
|
||||
- PVC 1Gi local-path, AOF on, maxmemory 256mb allkeys-lru
|
||||
- Manifest : `k3s/app/redis.yml`
|
||||
- Re-déployé par le workflow API (path filter inclut `redis.yml`)
|
||||
|
||||
### Infra commune
|
||||
- Domaine : https://app.rubis.arthurbarre.fr (DNS A 5413305619)
|
||||
- Route Traefik : `~/dev/perso/proxmox/ansible/roles/traefik/templates/rubis-app.yml.j2`
|
||||
- Workflow CI : `.gitea/workflows/deploy-app.yml`
|
||||
- Source : `apps/api`, `apps/web`, `packages/shared` (monorepo pnpm)
|
||||
|
||||
### Dépendances externes (déjà déployées)
|
||||
- **Postgres** : 10.10.10.3:5432, base `rubis_prod`, user `rubis`
|
||||
@ -66,25 +91,31 @@ kubectl --kubeconfig ~/dev/perso/proxmox/k3s/kubeconfig.yaml \
|
||||
```
|
||||
|
||||
### Mise à jour
|
||||
Push git, le CI build l'image (`Dockerfile.app`, multi-stage), apply les
|
||||
manifests `k3s/app/`, set image, rollout auto. Filter sur `apps/**`,
|
||||
`packages/**`, `Dockerfile.app`, `k3s/app/**`.
|
||||
Push git → un (ou les deux) workflow(s) CI se déclenchent selon les paths
|
||||
modifiés. Build+rollout indépendants.
|
||||
|
||||
### Particularités du Dockerfile.app
|
||||
- `node ace build` plante en CI avec `ERR_UNKNOWN_FILE_EXTENSION` car
|
||||
| Path modifié | Workflow déclenché |
|
||||
|---|---|
|
||||
| `apps/web/**`, `Dockerfile.web`, `k3s/app/web.yml` | deploy-web.yml |
|
||||
| `apps/api/**`, `Dockerfile.api`, `k3s/app/api.yml`, `k3s/app/redis.yml` | deploy-api.yml |
|
||||
| `packages/shared/**`, `pnpm-lock.yaml`, `tsconfig.base.json`, … | les deux |
|
||||
|
||||
### Particularités du Dockerfile.api
|
||||
- `node ace build` plante avec `ERR_UNKNOWN_FILE_EXTENSION` car
|
||||
`@poppinss/ts-exec` ne s'enregistre pas à temps avant l'import de
|
||||
`bin/console.ts`. **Solution** : on appelle ace via `tsx` (esbuild),
|
||||
qui gère nativement les `.ts` → `pnpm exec tsx ace.js build --ignore-ts-errors`
|
||||
`bin/console.ts`. **Solution** : `pnpm exec tsx ace.js build
|
||||
--ignore-ts-errors` (tsx = esbuild, gère .ts nativement).
|
||||
- `--ignore-ts-errors` car `tests/bootstrap.ts` référence un type généré
|
||||
dans `.adonisjs/client/registry/schema.d.ts` qui arrive trop tard. Le
|
||||
typecheck strict est exécuté côté CI séparément (`pnpm typecheck`).
|
||||
- Vite build appelé directement (`pnpm exec vite build`) au lieu de
|
||||
`pnpm build` qui fait `tsc -b && vite build` — le `tsc -b` plante sans
|
||||
cache `.tsbuildinfo` à cause de @tanstack/router-core.
|
||||
- SPA dist (`apps/web/dist`) copié dans `apps/api/build/public/` pour
|
||||
être servi par le static middleware AdonisJS. Une route wildcard
|
||||
(`start/routes.ts`) sert `index.html` pour les chemins non-API → SPA
|
||||
routing TanStack Router.
|
||||
tardivement (`.adonisjs/client/registry/schema.d.ts`). Le typecheck
|
||||
strict est exécuté en CI séparée (`pnpm typecheck`).
|
||||
|
||||
### Particularités du Dockerfile.web
|
||||
- Vite build appelé directement (`pnpm exec vite build`) au lieu du
|
||||
script `tsc -b && vite build` qui plante sans cache `.tsbuildinfo` à
|
||||
cause de @tanstack/router-core.
|
||||
- nginx.conf inclut le upstream `rubis-api.rubis.svc.cluster.local:3333`.
|
||||
Si on renomme le service API, c'est ici qu'il faut mettre à jour
|
||||
(en plus du manifest).
|
||||
|
||||
---
|
||||
|
||||
@ -92,16 +123,28 @@ manifests `k3s/app/`, set image, rollout auto. Filter sur `apps/**`,
|
||||
|
||||
```bash
|
||||
TAG=$(git rev-parse --short HEAD)
|
||||
# Landing
|
||||
# Landing (rubis.arthurbarre.fr)
|
||||
docker build --platform linux/amd64 -t git.arthurbarre.fr/ordinarthur/rubis:$TAG .
|
||||
docker push git.arthurbarre.fr/ordinarthur/rubis:$TAG
|
||||
kubectl --kubeconfig ~/dev/perso/proxmox/k3s/kubeconfig.yaml \
|
||||
-n rubis set image deploy/rubis rubis=git.arthurbarre.fr/ordinarthur/rubis:$TAG
|
||||
# App
|
||||
docker build --platform linux/amd64 -f Dockerfile.app -t git.arthurbarre.fr/ordinarthur/rubis-app:$TAG .
|
||||
docker push git.arthurbarre.fr/ordinarthur/rubis-app:$TAG
|
||||
|
||||
# App — web (frontend)
|
||||
docker build --platform linux/amd64 -f Dockerfile.web \
|
||||
-t git.arthurbarre.fr/ordinarthur/rubis-web:$TAG .
|
||||
docker push git.arthurbarre.fr/ordinarthur/rubis-web:$TAG
|
||||
kubectl --kubeconfig ~/dev/perso/proxmox/k3s/kubeconfig.yaml \
|
||||
-n rubis set image deploy/rubis-app app=git.arthurbarre.fr/ordinarthur/rubis-app:$TAG
|
||||
-n rubis set image deploy/rubis-web web=git.arthurbarre.fr/ordinarthur/rubis-web:$TAG
|
||||
|
||||
# App — api (backend)
|
||||
docker build --platform linux/amd64 -f Dockerfile.api \
|
||||
-t git.arthurbarre.fr/ordinarthur/rubis-api:$TAG .
|
||||
docker push git.arthurbarre.fr/ordinarthur/rubis-api:$TAG
|
||||
kubectl --kubeconfig ~/dev/perso/proxmox/k3s/kubeconfig.yaml \
|
||||
-n rubis set image deploy/rubis-api api=git.arthurbarre.fr/ordinarthur/rubis-api:$TAG \
|
||||
&& kubectl --kubeconfig ~/dev/perso/proxmox/k3s/kubeconfig.yaml \
|
||||
-n rubis patch deploy/rubis-api --type=json \
|
||||
-p="[{\"op\":\"replace\",\"path\":\"/spec/template/spec/initContainers/0/image\",\"value\":\"git.arthurbarre.fr/ordinarthur/rubis-api:$TAG\"}]"
|
||||
```
|
||||
|
||||
⚠️ Cross-compile ARM Mac → linux/amd64 plante sur `@swc/core` au build de
|
||||
@ -126,8 +169,9 @@ challenge LE).
|
||||
---
|
||||
|
||||
## Déjà fait — NE PAS refaire
|
||||
- Dockerfile (landing) + Dockerfile.app (app)
|
||||
- Manifests `k3s/` (landing) + `k3s/app/` (app + Redis)
|
||||
- Dockerfile (landing) + Dockerfile.web + Dockerfile.api (app split)
|
||||
- nginx.conf (apps/web/nginx.conf) avec upstream rubis-api
|
||||
- Manifests `k3s/` (landing) + `k3s/app/{api,web,redis}.yml`
|
||||
- Routes Traefik `rubis.yml.j2` + `rubis-app.yml.j2`
|
||||
- DNS OVH : A records `rubis` (id 5413044152) + `app.rubis` (id 5413305619)
|
||||
- Repo Gitea + secrets CI (`KUBECONFIG`, `REGISTRY_PASSWORD`)
|
||||
@ -135,5 +179,6 @@ challenge LE).
|
||||
- Postgres : base `rubis_prod` + user `rubis` (10.10.10.3)
|
||||
- MinIO : bucket `rubis-prod-invoices`
|
||||
- Secret K3s `rubis-app-secrets` (APP_KEY, DB pwd, MinIO, Resend, Mistral)
|
||||
- ConfigMap `rubis-api-config` (env non-sensibles)
|
||||
|
||||
Les prochains `/deploy` font uniquement build + rollout via push git.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user