Déploiement¶
La production tourne sur Dokploy, en Docker Compose, à partir de la branche main du dépôt. Pas de base de données ni de volume : un seul conteneur sert le client et le WebSocket.
flowchart LR
DEV["git push origin main"] --> GH["GitHub<br/>DuncanCos/orapamine"]
GH -->|"auto-deploy"| DOK["Dokploy<br/>projet orapamine"]
DOK -->|"docker compose build + up"| CTN["Conteneur orapamine<br/>port 8080"]
USER["Navigateur"] -->|"HTTPS / WSS"| PROXY["Reverse proxy Dokploy<br/>Let's Encrypt"]
PROXY -->|"orapamine.dunkan.xyz"| CTN
Image Docker¶
Dockerfile multi-étapes :
| Étape | Image de base | Ce qu'elle fait | Produit |
|---|---|---|---|
wasm-builder |
rust:1-slim-bookworm |
Ajoute la cible wasm32-unknown-unknown, installe wasm-bindgen-cli 0.2.127, compile orapa-wasm, génère les bindings (--target web --typescript) |
/app/wasm-out |
web-builder |
node:22-slim |
npm ci, copie les bindings dans web/src/wasm, puis npx tsc -b && npx vite build (sans build:wasm, déjà fait) |
/app/web/dist |
server-builder |
rust:1-slim-bookworm |
cargo build --release -p orapa-server |
binaire orapa-server |
runtime |
debian:bookworm-slim |
ca-certificates, utilisateur système orapa, copie du binaire et de web/dist |
image finale |
Image finale :
USER orapa,WORKDIR /appENV ORAPA_STATIC_DIR=/app/web/dist,ENV PORT=8080,EXPOSE 8080ENTRYPOINT ["./orapa-server"]
.dockerignore exclut target/, web/node_modules/, web/dist/, web/src/wasm/, .git/ et *.md.
Note
data/pieces.json est embarqué dans les binaires à la compilation : il n'est pas lu à l'exécution, et toute modification demande une reconstruction de l'image.
docker-compose.yml¶
services:
orapamine:
build: .
ports:
- "8080:8080"
environment:
- RUST_LOG=info
restart: unless-stopped
| Variable | Valeur dans l'image / le compose | Rôle |
|---|---|---|
PORT |
8080 (Dockerfile) |
Port d'écoute |
ORAPA_STATIC_DIR |
/app/web/dist (Dockerfile) |
Fichiers statiques du client |
RUST_LOG |
info (compose) |
Niveau de log |
Test local de l'image : docker compose up --build, puis http://localhost:8080.
Mapping de port
ports: "8080:8080" publie aussi le port 8080 directement sur l'hôte. Le domaine de production passe par le reverse proxy de Dokploy, qui cible le service orapamine sur le port 8080. Ce mapping ne lui est donc pas nécessaire.
Configuration Dokploy¶
| Paramètre | Valeur |
|---|---|
| Projet | orapamine (environnement production) |
| Service | Docker Compose orapamine |
| Source | GitHub DuncanCos/orapamine, branche main |
| Fichier compose | ./docker-compose.yml |
| Domaine | https://orapamine.dunkan.xyz, chemin /, vers le service orapamine, port 8080 |
| HTTPS | Certificat Let's Encrypt |
| Auto-deploy | Activé : chaque push sur main redéploie |
Aucune variable d'environnement n'est nécessaire en plus de celles de l'image et du compose. Le WebSocket utilise le même domaine (wss://orapamine.dunkan.xyz/ws).
Redéployer¶
Projet orapamine, puis service compose orapamine, puis Deploy. Les journaux de build et d'exécution sont consultables depuis le service.
Avec le wrapper dokploy (clé dans ~/.dokploy.env, à ne jamais afficher) :
# Retrouver le composeId
dokploy GET project.all | jq -r '.[] | select(.name=="orapamine") | .environments[].compose[] | "\(.name) \(.composeId)"'
# Lancer un déploiement
dokploy POST compose.deploy '{"composeId":"<composeId>"}'
# Suivre le statut (done, running, error…)
dokploy GET "compose.one?composeId=<composeId>" | jq -r .composeStatus
Warning
La réponse de compose.one contient aussi la configuration complète du service (champ env compris). Filtrer avec jq plutôt que de l'afficher en entier.
Vérifier après un déploiement¶
composeStatusvautdonedans Dokploy.- https://orapamine.dunkan.xyz répond (HTTP 200 sur
/, le client se charge). - Créer une partie solo : si le plateau et les tirs répondent, le WebSocket fonctionne.
Un redéploiement coupe les parties en cours
Les parties ne vivent qu'en mémoire du processus serveur. Chaque redéploiement (donc chaque push sur main) redémarre le conteneur et perd toutes les parties en cours. Les clients tentent de se reconnecter et reçoivent reconnect_failed. Il n'y a pas d'endpoint de santé dédié : / sert index.html.