Files
Infra/bonsai/docker-compose.yml
Gato 30887c066b feat(bonsai): la prod tire l'image publiée par la CI au lieu de la recompiler
Le service api clonait le dépôt et compilait le JAR sur le serveur à chaque
« docker compose build » (Dockerfile.api + secret ssh_key + CACHEBUST). La prod
rebuildait donc ce que la CI avait déjà buildé, sans garantie que les deux
partent du même commit — et aucune image publiée n'atteignait jamais la prod.

Elle tire maintenant …/bonsai-api:main et porte le label watchtower.enable : le
redéploiement suit tout seul chaque merge sur main, comme pour Luz. Le webapp,
lui, continue d'être buildé depuis les sources — d'où le secret ssh_key conservé.

Prérequis : de quoi tirer les images privées de l'org Bonsai. Le PAT de Watchtower
n'a aujourd'hui le scope read:package que sur Luz ; sans extension à Bonsai, le
pull échoue en silence (/v1/update répond 200, la prod ne bouge pas).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 14:02:24 +02:00

103 lines
3.4 KiB
YAML

name: bonsai
services:
db:
image: postgres:16-alpine
container_name: bonsai-db
restart: unless-stopped
environment:
POSTGRES_DB: bonsai
POSTGRES_USER: bonsai
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
TZ: Europe/Paris
healthcheck:
test: ["CMD-SHELL", "pg_isready -U bonsai -d bonsai"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- ~/Applications/data/bonsai/db_data:/var/lib/postgresql/data
networks:
- bonsai-net
# Image tirée du registre Gitea, publiée par la CI du dépôt Bonsai-api
# (.gitea/workflows/images.yml) à chaque push sur main. Le tag « main » suit la
# tête de cette branche ; « sha-<court> » permet d'épingler un commit précis en
# cas de rollback.
#
# Avant, ce service clonait le dépôt et compilait le JAR sur le serveur à chaque
# « docker compose build » (Dockerfile.api + secret ssh_key + CACHEBUST) : la prod
# rebuildait ce que la CI avait déjà buildé, et rien ne garantissait que les deux
# partaient du même commit. Le redéploiement est désormais automatique — le label
# watchtower.enable ci-dessous fait recréer ce conteneur dès que la CI publie une
# nouvelle image.
#
# Prérequis : le serveur doit pouvoir tirer les images privées de l'org Bonsai —
# soit via un « docker login git.goutailler-olivier.com » (root), soit via les
# REPO_USER/REPO_PASS de la stack Watchtower, dont le PAT doit avoir le scope
# read:package sur l'org Bonsai (et pas seulement sur Luz).
api:
image: git.goutailler-olivier.com/bonsai/bonsai-api:main
container_name: bonsai-api
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
DATASOURCE_URL: jdbc:postgresql://db:5432/bonsai
DATASOURCE_USERNAME: bonsai
DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD}
KEYCLOAK_JWKS_URI: https://auth.goutailler-olivier.com/realms/bonsai/protocol/openid-connect/certs
CORS_ALLOWED_ORIGIN_PROD: https://bonsai.goutailler-olivier.com
SERVER_SERVLET_CONTEXT_PATH: /api
TZ: Europe/Paris
volumes:
- ~/Applications/data/bonsai/uploads:/app/uploads
networks:
- bonsai-net
- proxy
labels:
- com.centurylinklabs.watchtower.enable=true
- traefik.enable=true
- traefik.http.routers.bonsai-api.rule=Host(`bonsai.goutailler-olivier.com`) && PathPrefix(`/api`)
- traefik.http.routers.bonsai-api.entrypoints=websecure
- traefik.http.routers.bonsai-api.tls.certresolver=le
- traefik.http.services.bonsai-api.loadbalancer.server.port=8080
- traefik.docker.network=proxy
webapp:
build:
context: .
dockerfile: Dockerfile.webapp
secrets:
- ssh_key
args:
CACHEBUST: ${CACHEBUST:-stable}
container_name: bonsai-webapp
restart: unless-stopped
depends_on:
- api
environment:
TZ: Europe/Paris
networks:
- bonsai-net
- proxy
labels:
- traefik.enable=true
- traefik.http.routers.bonsai-webapp.rule=Host(`bonsai.goutailler-olivier.com`)
- traefik.http.routers.bonsai-webapp.entrypoints=websecure
- traefik.http.routers.bonsai-webapp.tls.certresolver=le
- traefik.http.services.bonsai-webapp.loadbalancer.server.port=80
- traefik.docker.network=proxy
networks:
bonsai-net:
driver: bridge
proxy:
external: true
name: proxy
secrets:
ssh_key:
file: ${SSH_KEY_PATH}