Compare commits
2 Commits
23ce5c86e1
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7ae0d9f87f | |||
| 30887c066b |
@@ -1,20 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
FROM eclipse-temurin:25-jdk AS builder
|
|
||||||
RUN apt-get update && apt-get install -y git openssh-client && rm -rf /var/lib/apt/lists/*
|
|
||||||
ARG CACHEBUST
|
|
||||||
RUN --mount=type=secret,id=ssh_key \
|
|
||||||
--mount=type=cache,target=/root/.gradle \
|
|
||||||
mkdir -p /root/.ssh && \
|
|
||||||
cp /run/secrets/ssh_key /root/.ssh/id_ed25519 && \
|
|
||||||
chmod 600 /root/.ssh/id_ed25519 && \
|
|
||||||
ssh-keyscan -p 2222 git.goutailler-olivier.com >> /root/.ssh/known_hosts && \
|
|
||||||
git clone --depth 1 --branch main \
|
|
||||||
ssh://git@git.goutailler-olivier.com:2222/Gato/Bonsai-api.git /src && \
|
|
||||||
cd /src && ./gradlew bootJar --no-daemon -q
|
|
||||||
|
|
||||||
FROM eclipse-temurin:25-jre-alpine
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=builder /src/build/libs/*.jar app.jar
|
|
||||||
EXPOSE 8080
|
|
||||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
|
||||||
+27
-11
@@ -2,21 +2,25 @@
|
|||||||
|
|
||||||
Stack Docker Compose unifiée pour l'application Bonsai : base de données, API et webapp.
|
Stack Docker Compose unifiée pour l'application Bonsai : base de données, API et webapp.
|
||||||
|
|
||||||
Les images sont **buildées depuis les sources** de la branche `main` de chaque dépôt au moment du build. La clé SSH est transmise au build via un secret BuildKit — elle n'est jamais gravée dans les couches de l'image.
|
Les deux composants ne se déploient pas de la même façon :
|
||||||
|
|
||||||
|
- **`api`** — image **tirée du registre Gitea** (`git.goutailler-olivier.com/bonsai/bonsai-api:main`), publiée par la CI du dépôt `Bonsai-api` (`.gitea/workflows/images.yml`) à chaque merge sur `main`. Le redéploiement est automatique : le conteneur porte le label `com.centurylinklabs.watchtower.enable=true`, donc Watchtower (`../watchtower/`) le recrée dès qu'une nouvelle image est publiée. Rien à builder sur le serveur.
|
||||||
|
- **`webapp`** — toujours **buildé depuis les sources** de la branche `main` du dépôt `Bonsai-webapp`. La clé SSH est transmise au build via un secret BuildKit — elle n'est jamais gravée dans les couches de l'image.
|
||||||
|
|
||||||
## Services
|
## Services
|
||||||
|
|
||||||
| Service | Image de base | Source |
|
| Service | Image | Provenance |
|
||||||
|---------|--------------|--------|
|
|---------|-------|------------|
|
||||||
| `db` | `postgres:16-alpine` | — |
|
| `db` | `postgres:16-alpine` | — |
|
||||||
| `api` | `eclipse-temurin:25-jdk` → `25-jre-alpine` | `Bonsai-api` (branche `main`) |
|
| `api` | `git.goutailler-olivier.com/bonsai/bonsai-api:main` | CI de `Bonsai-api` (merge sur `main`) |
|
||||||
| `webapp` | `node:22-alpine` → `nginx:alpine` | `Bonsai-webapp` (branche `main`) |
|
| `webapp` | `node:22-alpine` → `nginx:alpine` | build local depuis `Bonsai-webapp` (branche `main`) |
|
||||||
|
|
||||||
## Prérequis
|
## Prérequis
|
||||||
|
|
||||||
- Docker avec BuildKit activé (Docker 23+)
|
- Docker avec BuildKit activé (Docker 23+)
|
||||||
- Une clé SSH ayant accès au dépôt Gitea (`git.goutailler-olivier.com:2222`)
|
- Une clé SSH ayant accès au dépôt Gitea (`git.goutailler-olivier.com:2222`) — pour le build du `webapp`
|
||||||
- Réseau Docker externe `proxy` (Traefik)
|
- Réseau Docker externe `proxy` (Traefik)
|
||||||
|
- De quoi tirer les images privées de l'org **Bonsai** : soit un `docker login git.goutailler-olivier.com` fait une fois en root sur le serveur, soit les `REPO_USER`/`REPO_PASS` de la stack Watchtower, dont le PAT doit porter le scope `read:package` sur l'org Bonsai. Sans cela, Watchtower échoue silencieusement à tirer l'image (`unauthorized: reqPackageAccess`) et la prod reste sur l'ancienne version, alors que l'appel à `/v1/update` répond bien 200.
|
||||||
|
|
||||||
## Démarrage
|
## Démarrage
|
||||||
|
|
||||||
@@ -25,7 +29,8 @@ Les images sont **buildées depuis les sources** de la branche `main` de chaque
|
|||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# Éditer .env : définir POSTGRES_PASSWORD et SSH_KEY_PATH
|
# Éditer .env : définir POSTGRES_PASSWORD et SSH_KEY_PATH
|
||||||
|
|
||||||
# 2. Builder les images (clone + compile)
|
# 2. Tirer l'image de l'API + builder le webapp
|
||||||
|
docker compose pull
|
||||||
docker compose build
|
docker compose build
|
||||||
|
|
||||||
# 3. Démarrer la stack
|
# 3. Démarrer la stack
|
||||||
@@ -34,14 +39,25 @@ docker compose up -d
|
|||||||
|
|
||||||
## Mise à jour
|
## Mise à jour
|
||||||
|
|
||||||
Pour rebuilder depuis le dernier commit de `main` (sans tout reconstruire) :
|
L'API se met à jour **toute seule** à chaque merge sur `main` de `Bonsai-api` (CI → registre → Watchtower). Aucune action ici.
|
||||||
|
|
||||||
|
Pour forcer un redéploiement, ou pour rebuilder le webapp depuis le dernier commit de sa branche `main` :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
CACHEBUST=$(date +%s) docker compose build
|
./deploy.sh
|
||||||
docker compose up -d
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`CACHEBUST` invalide uniquement l'étape clone+build. Les couches précédentes (installation des outils, image de base) restent en cache — le build reste rapide.
|
`CACHEBUST` (posé par le script) invalide uniquement l'étape clone+build du webapp. Les couches précédentes (installation des outils, image de base) restent en cache — le build reste rapide.
|
||||||
|
|
||||||
|
### Revenir à une version précédente de l'API
|
||||||
|
|
||||||
|
Chaque publication pose aussi un tag immuable `sha-<court>`. Pour épingler un commit :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
image: git.goutailler-olivier.com/bonsai/bonsai-api:sha-ccc20bf
|
||||||
|
```
|
||||||
|
|
||||||
|
puis `docker compose up -d api`. Watchtower ne touche pas à un tag figé qui ne bouge plus — repasser sur `:main` pour réactiver le suivi automatique.
|
||||||
|
|
||||||
## Arrêt
|
## Arrêt
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Déploiement manuel de la stack Bonsai.
|
||||||
|
#
|
||||||
|
# L'API n'est plus buildée ici : son image est publiée par la CI du dépôt
|
||||||
|
# Bonsai-api à chaque merge sur main, et Watchtower recrée le conteneur tout seul.
|
||||||
|
# Ce script sert donc au premier démarrage, à un changement de la stack ou à un
|
||||||
|
# redéploiement forcé — « pull » va chercher la dernière image de l'API, « build »
|
||||||
|
# ne concerne plus que le webapp (toujours compilé depuis les sources).
|
||||||
|
|
||||||
|
docker compose pull
|
||||||
CACHEBUST=$(date +%s) docker compose build
|
CACHEBUST=$(date +%s) docker compose build
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|||||||
@@ -20,14 +20,24 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- bonsai-net
|
- 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:
|
api:
|
||||||
build:
|
image: git.goutailler-olivier.com/bonsai/bonsai-api:main
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile.api
|
|
||||||
secrets:
|
|
||||||
- ssh_key
|
|
||||||
args:
|
|
||||||
CACHEBUST: ${CACHEBUST:-stable}
|
|
||||||
container_name: bonsai-api
|
container_name: bonsai-api
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -47,6 +57,7 @@ services:
|
|||||||
- bonsai-net
|
- bonsai-net
|
||||||
- proxy
|
- proxy
|
||||||
labels:
|
labels:
|
||||||
|
- com.centurylinklabs.watchtower.enable=true
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.bonsai-api.rule=Host(`bonsai.goutailler-olivier.com`) && PathPrefix(`/api`)
|
- 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.entrypoints=websecure
|
||||||
|
|||||||
@@ -16,7 +16,10 @@ services:
|
|||||||
# Sans eux, Watchtower échoue à tirer luz-backend/luz-webapp :main
|
# Sans eux, Watchtower échoue à tirer luz-backend/luz-webapp :main
|
||||||
# (« unauthorized: reqPackageAccess ») et ne recrée jamais les conteneurs
|
# (« unauthorized: reqPackageAccess ») et ne recrée jamais les conteneurs
|
||||||
# — le déploiement reste bloqué en silence (Updated=0, mais /v1/update → 200).
|
# — le déploiement reste bloqué en silence (Updated=0, mais /v1/update → 200).
|
||||||
# Un PAT en LECTURE seule (scope read:package) sur l'org Luz suffit.
|
# Un PAT en LECTURE seule (scope read:package) suffit — mais il lui faut
|
||||||
|
# accès aux DEUX organisations qui publient des images ici : Luz et, depuis
|
||||||
|
# que la stack bonsai tire bonsai-api du registre, Bonsai. Un PAT limité à
|
||||||
|
# Luz laisserait la prod Bonsai bloquée sur son ancienne image, en silence.
|
||||||
# Remplace l'ancien montage de /root/.docker/config.json, qui côté hôte
|
# Remplace l'ancien montage de /root/.docker/config.json, qui côté hôte
|
||||||
# ne contenait aucune auth (le docker login du CI a lieu sur le runner).
|
# ne contenait aucune auth (le docker login du CI a lieu sur le runner).
|
||||||
REPO_USER: ${REGISTRY_USER}
|
REPO_USER: ${REGISTRY_USER}
|
||||||
|
|||||||
Reference in New Issue
Block a user