Skip to main content

Architecture des conteneurs

Comment les images Docker de Tale sont structurées, construites et connectées.

8 min read

Tale tourne en six conteneurs Docker pilotés par Docker Compose, chacun avec une responsabilité unique et un port unique sur le réseau bridge interne. Cette page est le modèle mental de l'opérateur sur ce qui tourne, où, et comment les services se parlent : quels volumes sont partagés, quels ports sont exposés, où la topologie blue-green se replie sur elle-même pendant un déploiement. Ouvre-la quand quelque chose n'atterrit pas là où tu l'attends — un endpoint de métriques injoignable, un port exposé par erreur, une bascule blue-green qui n'a pas drainé proprement.

Les six conteneurs sont stables sur chaque chemin d'installation. Démarrage rapide, déploiement en production et CI montent tous le même ensemble ; seuls les mappages de ports, le mode TLS et les bindings d'hôte diffèrent.

Comment les services se parlent

100%

Le proxy est le seul conteneur qui écoute sur un port public. Tout le reste reste sur le bridge Docker interne ; la plateforme ne touche jamais Postgres directement parce que Convex possède chaque lecture et écriture qui atterrit dans la base. RAG et le crawler parlent à la base pour leurs propres tables par service (schémas tale_knowledge) mais ne lisent ni n'écrivent jamais les tables Convex.

Détails d'image

ServiceImage de baseTaille compresséeStratégie de build
Platformghcr.io/get-convex/convex-backend (pour le binaire glibc generate_key)~320 Mo5 étapes : deps → builder → pruner → runner → squash
Convexghcr.io/get-convex/convex-backend~485 Mo2 étapes : dashboard → runner (tableau de bord COPY depuis l'image amont)
Crawlerpython:3.11-slim~650 Mo3 étapes : builder → runtime → squash. Chromium headless_shell uniquement.
RAGpython:3.11-slim~515 Mo3 étapes : builder → runtime → squash. libpq5 uniquement.
DBparadedb/paradedb:0.22.5-pg16~1,06 Go3 étapes : cleanup → runtime → squash.
Proxycaddy:2.11-alpine~88 MoUne seule étape.

Sortir Convex de l'image plateforme a fait passer la couche plateforme d'environ 2,58 Go compressés à environ 320 Mo ; le nouveau service convex pèse environ 485 Mo. Le disque image net est similaire, mais la couche plateforme se reconstruit beaucoup plus vite pour les changements purement applicatifs — la plupart des pull requests ne touchent que la SPA ou le serveur Bun, et l'image plateforme est celle que la CI reconstruit à chaque merge.

Mappage de ports

Ports de développement (compose.yml)

ServicePort hôtePort conteneurProtocole
DB54325432TCP (PostgreSQL)
Crawler80028002HTTP
RAG80018001HTTP
Convex3210, 3211, 6791WS/HTTP (via proxy)
Platform3000HTTP (via proxy)
Proxy80, 44380, 443HTTP/HTTPS

Ports de test (compose.test.yml)

ServicePort hôtePort conteneur
DB154325432
Crawler180028002
RAG180018001
Convex13210, 13211, 167913210, 3211, 6791
Platform130003000
Proxy10080, 1044380, 443

Le fichier compose de développement expose les quatre ports backend sur l'hôte (5432, 8001, 8002) pour un accès direct depuis le portable du développeur ; le compose de production généré par tale deploy ne le fait pas — chaque port backend reste sur le bridge interne.

Mappage de volumes

VolumeMonté dansCheminRôle
db-dataDB/var/lib/postgresql/dataRépertoire de données PostgreSQL.
db-backupDB/var/lib/postgresql/backupSauvegardes de base de données.
rag-dataRAG/app/dataFichiers temporaires, traitement des documents.
crawler-dataCrawler/app/dataRegistre de sites web, bases d'URL.
convex-dataConvex/app/dataBase Convex (SQLite/pg-local), index de recherche, fichiers, agents/workflows/intégrations/fournisseurs JSON semés.
convex-dataPlatform/app/data (lecture seule)Veille SSE de configuration et service d'images de marque.
convex-dataCrawler, RAG/app/platform-config (lecture seule)Config de fournisseur partagée.
caddy-dataProxy, Convex/data, /caddy-dataCertificats TLS.
caddy-configProxy/configConfiguration Caddy.
platform-data(historique, démonté)Préservé après la mise à niveau de séparation Convex pour la sûreté du rollback. À retirer manuellement après vérification avec docker volume rm ....

Ne fais jamais tourner docker compose down -v. Le drapeau -v supprime chaque volume nommé, c'est-à-dire la base, chaque fichier téléversé, l'état du crawler et les certificats TLS. Pas de récupération possible.

Arguments de build

ArgumentDéfautUtilisé parDescription
VERSIONdevTousTag de version de l'image, posé par la CI depuis le tag git.
INSTALL_CJK_FONTSfalseCrawlerInstalle le support des polices CJK (~100 Mo).

Stratégie de build multi-étapes

Chaque service se termine par une étape FROM scratch de squash. Cette étape finale aplatit les couches Docker pour que les suppressions de fichiers dans les étapes de nettoyage précédentes récupèrent de l'espace disque au lieu d'ajouter des couches de masquage ; sans le squash, un rm -rf à l'étape quatre coûterait encore les octets supprimés dans l'image finale.

Platform (5 étapes, après scission)

  1. bun-bin — extrait le binaire Bun.
  2. workspace-deps — installe chaque dépendance npm, devDependencies incluses.
  3. builder — fait tourner vite build pour produire le bundle SPA.
  4. pruner — réinstalle les deps de production uniquement, retire les paquets de test et de développement.
  5. runner — runtime final sur l'image de base convex-backend (gardée pour le binaire glibc generate_key qui sert à signer les jetons admin Convex). SPA Vite et serveur Bun uniquement — pas de processus backend Convex.

Une étape squash sur FROM scratch puis COPY --from=runner produit l'image livrée. Le conteneur tourne brièvement en root, descend à l'utilisateur app via gosu dans l'entrypoint.

Convex (2 étapes, nouveau en Phase 2)

  1. convex-dashboardFROM ghcr.io/get-convex/convex-dashboard pour copier le build standalone Next.js.
  2. runnerFROM ghcr.io/get-convex/convex-backend. Contient le démon local-backend, le tableau de bord, les assets de seed intégrés (agents, workflows, intégrations, fournisseurs, image de marque) et l'entrypoint. Retire LLVM et Clang pour environ 155 Mo d'économies.

Crawler (3 étapes)

  1. builder — installe les dépendances Python via uv, télécharge Chromium headless_shell, fait tourner un nettoyage profond (retire le binaire Chrome complet, FFmpeg, pip, __pycache__, les symboles de debug .so, les répertoires de test).
  2. runtimepython:3.11-slim propre avec uniquement les bibliothèques système runtime (deps Chromium, tini, curl). Retire LLVM et le jeu d'icônes Adwaita.
  3. squashFROM scratch plus COPY --from=runtime. Préalloue les points de montage de volumes pour /app/data et /app/platform-config.

RAG (3 étapes)

  1. builder — installe les deps Python avec build-essential et libpq-dev pour compiler les paquets natifs, puis retire pip et setuptools.
  2. runtimepython:3.11-slim propre avec uniquement libpq5 et curl. Préalloue les points de montage de volumes.
  3. squashFROM scratch plus COPY --from=runtime.

DB (3 étapes)

  1. cleanup — retire les symboles de debug (environ 888 Mo), les bibliothèques partagées LLVM (environ 127 Mo), les fichiers de l'extension PostGIS, les locales et les docs depuis l'image de base ParadeDB.
  2. runtimeFROM scratch plus COPY --from=cleanup. Couche fraîche avec uniquement les fichiers nettoyés.
  3. squash — redéclare PGDATA, PATH et les autres variables ENV perdues pendant FROM scratch.

Health checks

ServiceEndpointProtocolePériode de démarrage
DBpg_isready -U tale -d taleCLI60s
CrawlerGET /health sur :8002HTTP40s
RAGGET /health sur :8001HTTP40s
ConvexGET :3210/version + [ -f /tmp/convex-ready ]HTTP + fichier60s
PlatformGET :3000/api/health + [ -f /tmp/platform-ready ]HTTP + fichier180s
ProxyGET /health sur :2020 (interne)HTTP10s

Les marqueurs /tmp/<service>-ready sont touchés par l'entrypoint de chaque service après que son travail d'initialisation en une passe se termine — Convex après que le backend est en marche et que le seed intégré atterrit ; la plateforme après que la synchronisation d'environnement et convex deploy réussissent. Le fichier marqueur est ce qui empêche le proxy de router le trafic vers un conteneur qui accepte les connexions mais n'est pas encore prêt à servir.

Test des conteneurs

Tale inclut trois scripts de test de conteneurs qui tournent en CI à chaque pull request et que tu peux faire tourner sur un hôte de développement avant de pousser :

ScriptCommandeCe qu'il teste
tests/container-smoke-test.shbun run docker:testBuilds, démarrages, health checks, endpoints HTTP, connectivité entre services.
tests/container-image-test.shbun run docker:test:imageLabels OCI, utilisateur non-root, pas de secrets, instruction HEALTHCHECK, budgets de taille.
tests/container-vulnerability-scan.shbun run docker:test:vulnerabilityAnalyse de vulnérabilités Trivy (HIGH + CRITICAL).

Le guide Contributing Docker couvre chaque script en détail.

Où cela s'insère

L'architecture des conteneurs est le modèle mental de ce qui tourne, où et comment les services se parlent. Ouvre-la quand quelque chose n'atterrit pas là où tu l'attends — un endpoint de métriques injoignable, un port exposé par erreur, une bascule blue-green qui n'a pas drainé proprement. Pour les surfaces d'observabilité par service, Exploitation est la page suivante ; pour les boutons en variable d'environnement, Référence d'environnement est exhaustive.

© 2026 Tale by Ruler GmbH — ISO 27001 & SOC 2 certified.

Tale is MIT licensed — free to use, modify, and distribute.