Docker¶
Images publiées¶
Chaque version est publiée pour linux/amd64 et linux/arm64 sur GitHub Container Registry et
Docker Hub, en deux variantes : SQLite seul, et -pg avec le pilote PostgreSQL.
docker pull ghcr.io/cyr-ius/security-review-mcp:latest-pg # or docker.io/cyrius44/security-review-mcp
| Tag | Contenu |
|---|---|
X.Y.Z, X.Y, X, latest |
Version X.Y.Z (la dernière version stable pour latest) |
X.Y.Z-pg, X.Y-pg, X-pg, latest-pg |
Idem, avec le pilote PostgreSQL |
X.Y.ZrcN (a, b, rc) |
Préversion : ce tag seulement, jamais latest |
Fixez une version (1.2.3-pg) en production. Les images portent un SBOM et une attestation de
provenance (docker buildx imagetools inspect --format '{{ json .Provenance }}' IMAGE). Dans
les exemples de cette page, remplacez security-review-mcp et security-review-mcp:pg par
l'image publiée, ou construisez-la.
Construire l'image¶
docker build -t security-review-mcp .
docker build -t security-review-mcp:pg --build-arg EXTRAS=postgres . # pilote PostgreSQL
Le build compile aussi l'interface web (étape Node.js) ;
elle est servie sur /ui/ par le contrôleur.
L'image tourne sous un utilisateur non root (uid 10001), sans sources ni outils de build. Son
HEALTHCHECK (python -m security_review_mcp.healthcheck, toutes les 30 secondes) interroge
/healthz du serveur MCP HTTP ou du contrôleur sur l'interface de bouclage, en HTTPS quand le
TLS est activé (en ne faisant confiance qu'au certificat du conteneur) ; en stdio, rien n'écoute
et le conteneur reste sain, et avec le TLS mutuel (SECREVIEW_TLS_CLIENT_CA) il n'interroge
rien : appuyez-vous sur les sondes de l'orchestrateur. La
base SQLite est dans le volume /var/lib/secreview. Le fichier .env n'est pas copié dans l'image :
passez la configuration avec -e ou --env-file.
Serveur partagé (HTTP)¶
Une seule image, deux conteneurs qui partagent la base (voir Architecture et déploiement) :
- le serveur MCP, point d'entrée par défaut de l'image (
security-review-mcp, commande par défautserve: stdio ; ajoutez--transport streamable-httppour HTTP) ; - le contrôleur (API REST, interface web, administration), lancé avec
--entrypoint security-review-controller.
Avec l'authentification et le TLS intégrés (ou derrière un reverse proxy qui s'en charge) :
DB=postgresql+psycopg2://user:pass@db:5432/secreview
# 1. Schéma (Alembic) : à relancer après chaque mise à jour de l'image
docker run --rm -e SECREVIEW_DATABASE_URL=$DB \
--entrypoint security-review-controller security-review-mcp:pg db upgrade
# 2. Contrôleur : interface web et API, de préférence sur un réseau interne
docker run -d --name secreview-controller -p 127.0.0.1:8080:8000 \
-e SECREVIEW_DATABASE_URL=$DB -e SECREVIEW_DB_AUTO_UPGRADE=false \
--entrypoint security-review-controller \
security-review-mcp:pg serve --host 0.0.0.0 --port 8000
# 3. Serveur MCP : exposé aux agents et à la CI
docker run -d --name secreview-mcp -p 8443:8443 \
-e SECREVIEW_DATABASE_URL=$DB \
-v ./tls:/etc/secreview/tls:ro \
-e SECREVIEW_TLS_CERTFILE=/etc/secreview/tls/cert.pem \
-e SECREVIEW_TLS_KEYFILE=/etc/secreview/tls/key.pem \
security-review-mcp:pg serve --transport streamable-http --host 0.0.0.0 --port 8443
Les fichiers montés doivent être lisibles par l'utilisateur du conteneur (uid 10001). Le
serveur MCP refuse de démarrer tant que le schéma n'est pas migré. Au premier démarrage du
contrôleur, le compte admin est créé avec un mot de passe aléatoire que personne ne connaît
et qui n'est jamais journalisé ; seule son empreinte est conservée, dans la base de données.
Définissez-le avec
docker exec secreview-controller security-review-controller user reset-password admin
(affiché une fois), connectez-vous sur l'interface (/ui/) avec l'identifiant admin, puis
choisissez votre propre mot de passe dans Mon compte. Créez ensuite un compte par
personne dans l'écran Utilisateurs (voir les
comptes utilisateurs).
Les jetons projet créés depuis l'écran Jetons sont eux aussi stockés sous forme d'empreinte dans la base, comme tous les jetons (voir jetons Bearer).
La CLI est le seul moyen d'obtenir le mot de passe initial
Aucune variable ne le définit et les journaux ne l'affichent jamais : lancez
user reset-password admin dans le conteneur, et traitez ce qu'elle affiche comme un secret.
Si vous le perdez, relancez la commande (l'ancien est aussitôt invalidé).
Docker Compose avec PostgreSQL¶
Le fichier docker-compose.yml à la racine du dépôt démarre les deux processus avec une base
PostgreSQL :
echo "POSTGRES_PASSWORD=$(openssl rand -hex 24)" > .env
docker compose up -d --build
docker compose exec controller security-review-controller user reset-password admin # mot de passe admin initial
| Service | Rôle | Écoute |
|---|---|---|
db |
PostgreSQL, joignable seulement sur le réseau interne backend |
— |
migrate |
security-review-controller db upgrade, puis s'arrête |
— |
controller |
API REST et interface web (/ui/) |
127.0.0.1:8080 (DOCKER_PUBLISH_ADDRESS, DOCKER_CONTROLLER_PORT) |
mcp |
Serveur MCP (/mcp) et enrôlement public |
127.0.0.1:8000 (DOCKER_PUBLISH_ADDRESS, DOCKER_MCP_PORT) |
- L'image est construite avec l'extra
postgres(security-review-mcp:pg).migrateattend que la base soit prête (pg_isready) ;controlleretmcpattendent quemigrateait réussi. Seulmigratemodifie le schéma (SECREVIEW_DB_AUTO_UPGRADE=falseailleurs). POSTGRES_PASSWORDest obligatoire et lu depuis.env(jamais commité). Il est inséré tel quel dansSECREVIEW_DATABASE_URL: utilisez des caractères hexadécimaux, ou encodez les caractères spéciaux (@,:,/...).- Les ports ne sont publiés que sur
127.0.0.1par défaut. Pour les exposer, activez le TLS intégré ou placez-les derrière un reverse proxy, puis indiquez l'adresse de l'hôte à utiliser dans.env:DOCKER_PUBLISH_ADDRESS=192.168.1.10(une interface) ouDOCKER_PUBLISH_ADDRESS=0.0.0.0(toutes les interfaces), et les ports de l'hôte dansDOCKER_MCP_PORTetDOCKER_CONTROLLER_PORT. Ces variables ne servent qu'à Compose : dans les conteneurs, les deux serveurs écoutent sur 8000. Le contrôleur n'expose aucune route d'écriture sans jeton : il peut rester interne. - Les variables de
.envne servent qu'à Compose : ajoutez-les sousenvironmentpour qu'elles atteignent les conteneurs (par exempleSECREVIEW_TLS_CERTFILEetSECREVIEW_TLS_KEYFILE, avec les fichiers du certificat montés en lecture seule, voir Autorité de certification). - La base d'avis de vulnérabilités est vide au premier démarrage : l'analyse de dépendances
répond alors qu'aucune base n'est chargée. Pour que le contrôleur la télécharge au démarrage
puis toutes les 24 h, ajoutez
SECREVIEW_OSV_AUTO_UPDATE=truedans.env(et, si besoin,SECREVIEW_OSV_ECOSYSTEMS,HTTPS_PROXYetNO_PROXY), que le fichier Compose transmet au seul contrôleur, puisdocker compose up -d. Suivez l'import avecdocker compose logs -f controllerou dans les paramètres de l'interface web. Sans accès Internet, importez une archive avecadvisories import(voir Dépendances). - Les conteneurs tournent en système de fichiers en lecture seule, sans capacité Linux. Le
volume
secreview-pgcontient les rapports, les comptes de l'interface web et les jetons : sauvegardez-le. - Le service
dbutilise PostgreSQL 18, dont l'image range les données dans un répertoire par version majeure : le volumesecreview-pgest monté sur/var/lib/postgresql(et non/var/lib/postgresql/data). Un volume créé par PostgreSQL 17 ne démarre pas avec cette image (Error: in 18+, these Docker images are configured to store database data in a format...) : voir Mise à niveau de PostgreSQL.
Pour ajouter le TLS ou des règles internes, complétez environment et volumes du service
concerné. Les commandes CLI s'exécutent dans le conteneur du contrôleur :
docker compose exec controller security-review-controller token list
Mise à niveau de PostgreSQL¶
Une version majeure de PostgreSQL ne lit pas les fichiers de données de la précédente. Pour
passer un volume secreview-pg de PostgreSQL 17 à 18, exportez la base avec l'ancienne image,
recréez le volume puis restaurez l'export :
# 1. Avec le fichier Compose précédent (postgres:17-alpine, montage sur /var/lib/postgresql/data)
docker compose stop mcp controller
(umask 077 && docker compose exec -T db pg_dump -U secreview -d secreview -Fc > ~/secreview.dump)
docker compose down
# 2. Vérifier l'export (il liste les tables), puis recréer le volume : l'export est désormais
# la seule copie des données
docker compose run --rm -T --no-deps --entrypoint pg_restore db --list < ~/secreview.dump | grep 'TABLE DATA'
docker volume rm security-review-mcp_secreview-pg
# 3. Avec le fichier Compose actuel (postgres:18-alpine, montage sur /var/lib/postgresql)
docker compose up -d db
docker compose exec -T db pg_restore -U secreview -d secreview --clean --if-exists --no-owner < ~/secreview.dump
docker compose up -d
Le service migrate applique ensuite les révisions Alembic en attente, s'il y en a. L'export
contient les rapports, les empreintes des mots de passe et des jetons : gardez-le hors du dépôt
(lisible par vous seul, umask 077) et supprimez-le une fois la restauration vérifiée.
Poste développeur (stdio)¶
L'hôte lance le conteneur. .mcp.json à la racine du dépôt (VS Code, GitHub Copilot et
Claude) :
{
"mcpServers": {
"security-review": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-v", "secreview-data:/var/lib/secreview", "security-review-mcp"]
}
}
}
-i mais pas -t
-i est indispensable (le protocole passe par stdin) ; ne mettez pas -t.
Règles internes et CLI¶
Les règles internes sont stockées dans la base : importez un dossier de packs TOML avec la CLI du contrôleur (les serveurs en cours d'exécution les appliquent en quelques secondes) :
docker run --rm -v secreview-data:/var/lib/secreview -v ./rules.d:/rules:ro \
--entrypoint security-review-controller security-review-mcp rules import /rules
Les autres commandes passent de la même façon :
docker run --rm -v secreview-data:/var/lib/secreview \
--entrypoint security-review-controller security-review-mcp token list