Déployer SkillBridge sur Coolify (VPS Hetzner)¶
Guide pas-à-pas pour mettre en ligne les trois services SkillBridge sur un VPS Hetzner géré par Coolify :
| Service | Domaine cible | Image | Rôle |
|---|---|---|---|
| API | api.skillbridge-data.fr |
Dockerfile.api |
Provider FastAPI |
| Front | app.skillbridge-data.fr |
Dockerfile.front |
Vitrine Streamlit |
| Doc | docs.skillbridge-data.fr |
Dockerfile.docs |
Doc MkDocs servie par nginx |
Le LRC n'est pas déployé en ligne : l'interopérabilité est démontrée par une
fixture committée (data/seed/interop_example/) que la vitrine lit en prod.
Pré-requis côté Coolify¶
- Une instance Coolify ≥ 4 sur ton VPS Hetzner (Coolify gère Traefik et Let's Encrypt automatiquement).
- Le domaine
skillbridge-data.frconfiguré chez ton registrar avec un enregistrement pointant vers l'IP publique du VPS (unAsur l'apex + unCNAME *.skillbridge-data.frvers l'apex, ou troisAséparés — au choix). - Un projet créé dans Coolify pour SkillBridge (ce sera le conteneur des 3 apps).
Pré-requis côté repo¶
Le repo peut être public ou privé — les artefacts (Dockerfiles, mapping) sont identiques. La seule différence est la méthode de connexion :
Connecte le repo via l'URL HTTPS directement dans Coolify (sans clé). Plus simple pour une démo ouverte.
- Génère une deploy key SSH Coolify : Sources → New SSH key.
- Ajoute la clé publique dans GitHub : Repo → Settings → Deploy keys → Add key (read only — la deploy key n'a accès qu'à ce repo).
- Dans Coolify : Sources → New private repository → URL SSH
(
git@github.com:sodigitaljeremy/skill-bridge.git) + la clé fraîchement créée.
Étape 1 — Créer l'app API¶
- Project → New Resource → Application (Docker build).
- Source : le repo SkillBridge.
- Branch :
main. - Dockerfile :
Dockerfile.api. - Port exposé :
8000. - Healthcheck :
- URL :
/health - Start period : 30 s (le temps de l'init lifespan + précompute des 100 recos)
- Interval : 10 s
- URL :
- Resources : pas de minimum critique, mais ~1.5 GB de RAM recommandés (torch + modèle ST chargés en mémoire + 5800 traces).
- Domaine :
api.skillbridge-data.fr(Coolify gère le TLS Let's Encrypt automatiquement). - Pas de variables d'environnement à poser — toutes les valeurs sont calées par défaut et le dataset est baked in à l'image.
Premier build
Le premier docker build côté Coolify prend 5-10 minutes : install des deps
(torch CPU ≈ 750 MB), téléchargement du modèle sentence-transformers (≈ 470 MB), et
make dataset. Les builds ultérieurs réutilisent les couches.
Étape 2 — Créer l'app Front¶
- Project → New Resource → Application.
- Source : même repo.
- Dockerfile :
Dockerfile.front. - Port :
8501. - Healthcheck : URL
/_stcore/health, start period 15 s. - Variable d'environnement :
(Coolify met les conteneurs sur un même réseau Docker ; on appelle l'API par son nom de service interne, pas par le domaine public — évite un aller-retour TLS.)
SKILLBRIDGE_API_URL=http://skillbridge-api:8000 - Domaine :
app.skillbridge-data.fr.
Étape 3 — Créer l'app Doc¶
- Project → New Resource → Application.
- Source : même repo.
- Dockerfile :
Dockerfile.docs. - Port :
80. - Healthcheck : URL
/healthz, interval 30 s. - Pas de variable d'environnement.
- Domaine :
docs.skillbridge-data.fr.
Étape 4 — Vérification¶
curl -sf https://api.skillbridge-data.fr/health | jq
# attendu : {"status":"ok","preloaded":true,"n_learners":100,...}
curl -sI https://app.skillbridge-data.fr/ | head -1
# attendu : HTTP/2 200
curl -sI https://docs.skillbridge-data.fr/ | head -1
# attendu : HTTP/2 200
Ouvre https://app.skillbridge-data.fr/ dans un navigateur et vérifie les 3 écrans :
- Vue d'ensemble : encart interopérabilité chargé depuis la fixture (Léa Martin, EX011, statement xAPI).
- Apprenant : Léa par défaut, recos visibles, profil cohérent.
- Clustering : silhouette par k, heatmap, projection PCA, et table de pureté
cluster ↔ archétype alimentée par
data/seed/learners_fixture.jsonl.
Surveillance et journaux¶
- Coolify expose les logs en temps réel par service (UI ou
coolify logs <app>). - L'API logue son boot via
uvicorn; tu dois voir une ligneStarted server processaprès ~5 s, puis l'app reste prête. - En cas de Crash de l'API : le précompute des recos ou le chargement du modèle ST sont les deux suspects naturels. Vérifie la RAM disponible.
Redéploiement¶
- Push sur
main→ Coolify déclenche un rebuild automatique (si webhook activé). - Sinon, Application → Deploy dans l'UI.
- Pour les fixtures (interop_example, learners_fixture) : un push standard suffit — elles sont dans l'image.
- Pour le modèle ST : pas de rebuild forcé sauf si tu changes
Dockerfile.apiou son stagest-bundle.
Limites assumées¶
- Pas de scaling horizontal : la précomputation au
lifespanfait que chaque instance a son propre cache mémoire. Pour > 1 réplique, il faudrait externaliser le cache (Redis) ou passer à un mode stateless — hors scope niveau 1. - Pas d'auth : l'API et la vitrine sont publiques. Si tu veux limiter l'accès pendant la candidature, ajoute une basic auth Traefik dans Coolify (UI → Labels).
- Pas de monitoring externe : pas de Sentry, pas de Prometheus exporter. Les logs Coolify suffisent à ce stade.