Aller au contenu

Docker

Images publiées

Chaque version est publiée pour linux/amd64 et linux/arm64 sur GitHub Container Registry et Docker Hub. La même image fonctionne avec SQLite et PostgreSQL : elle contient le pilote PostgreSQL.

docker pull ghcr.io/cyr-ius/security-review:latest   # or docker.io/cyrius44/security-review
Tag Contenu
X.Y.Z, X.Y, X, latest Version X.Y.Z (la dernière version stable pour latest)
X.Y.Z-opengrep, X.Y-opengrep, X-opengrep, latest-opengrep Même version avec le moteur OpenGrep (environ 250 Mo de plus) et ses règles par défaut, installées au démarrage
X.Y.Z-pg, X.Y-pg, X-pg, latest-pg Dépréciés : alias de la même image, conservés jusqu'à la prochaine version majeure (ancienne variante PostgreSQL)
X.Y.ZrcN (a, b, rc) Préversion : ce tag seulement, jamais latest

Utilisez l'image -opengrep pour le serveur Controller seulement si vous exécutez des règles OpenGrep : le serveur MCP n'exécute jamais OpenGrep et garde l'image par défaut. Pour les construire localement : docker build . ou docker build --target opengrep ..

Les images portent un SBOM et une attestation de provenance (docker buildx imagetools inspect --format '{{ json .Provenance }}' IMAGE).

Choisir le processus

Le premier argument donné à l'image choisit le processus qu'elle lance :

Commande Processus
mcp (par défaut) Serveur MCP (security-review-mcp serve), en HTTP streamable ou en stdio selon SECREVIEW_TRANSPORT (http par défaut, ou stdio)
mcp ARGS… security-review-mcp ARGS… (par exemple mcp enroll)
controller Serveur Controller (security-review-controller serve) : API REST, interface web
controller ARGS… une commande du serveur Controller (par exemple controller token list)
docker run -d -p 127.0.0.1:8080:8000 ghcr.io/cyr-ius/security-review controller   # Controller server
docker run -d -p 127.0.0.1:8000:8000 ghcr.io/cyr-ius/security-review mcp          # MCP server (HTTP)

En stdio, l'hôte d'un développeur (VS Code, Claude…) démarre lui-même le conteneur et lui parle sur stdin / stdout (mode local, base SQLite locale dans le volume). Dans .mcp.json :

{
  "mcpServers": {
    "security-review": {
      "type": "stdio",
      "command": "docker",
      "args": ["run", "-i", "--rm", "-e", "SECREVIEW_TRANSPORT=stdio",
               "-v", "secreview-mcp:/var/lib/secreview",
               "ghcr.io/cyr-ius/security-review:latest", "mcp"]
    }
  }
}

-i est indispensable (l'hôte écrit sur l'entrée standard du conteneur). En stdio, le serveur refuse une SECREVIEW_DATABASE_URL PostgreSQL : pour travailler sur la base de l'équipe, connectez l'hôte au serveur MCP partagé en HTTP. Les autres arguments sont passés à security-review-mcp, et --entrypoint security-review-controller fonctionne toujours.

Docker Compose avec PostgreSQL

Un seul fichier, examples/docker/docker-compose.yml, démarre tout avec l'image publiée : PostgreSQL, la migration du schéma, le serveur Controller et le serveur MCP. Les commandes qui le téléchargent et le démarrent sont dans Mise en service du serveur.

La commande printf écrit le fichier .env, lisible par vous seul : le mot de passe de PostgreSQL et le secret des sessions web, tirés au hasard. docker compose up -d --wait rend la main une fois tous les services prêts. L'interface web répond sur http://127.0.0.1:8080/ui/, l'endpoint MCP sur http://127.0.0.1:8000/mcp.

Contenu des fichiers de la version v11.0.0 :

# security-review with PostgreSQL, ready to use: download this file in an empty folder,
# create the .env file next to it, then start everything.
#
#   (umask 077 && printf 'POSTGRES_PASSWORD=%s\nSECREVIEW_SECRET_KEY=%s\n' \
#       "$(openssl rand -hex 24)" "$(openssl rand -hex 32)" > .env)
#   docker compose up -d --wait
#   docker compose exec controller security-review-controller user reset-password admin
#
# Web interface: http://127.0.0.1:8080/ui/   MCP endpoint: http://127.0.0.1:8000/mcp
#
# Three services:
#   db          PostgreSQL (official image), reachable by the other services only
#   controller  web interface and REST API (for people); creates or updates the tables at start
#   mcp         MCP server (for the AI agents and the CI), started once the controller is ready
#
# The two ports are published on every interface of the server, for the team: enable TLS (the
# commented TLS lines of controller and mcp) or put a reverse proxy in front (see the
# documentation, page Docker), plain HTTP exposes the tokens.
# To keep a port on this machine only, prefix it with 127.0.0.1 ("127.0.0.1:8000:8000").
# Inside their containers, the servers always listen on every interface (set by the image):
# only the ports choose the exposure.

name: security-review

services:
  db:
    image: postgres:18-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: secreview
      POSTGRES_USER: secreview
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      # Since PostgreSQL 18, the data is kept under /var/lib/postgresql/18/docker
      - secreview-pg:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U secreview -d secreview"]
      interval: 10s
      timeout: 5s
      retries: 5
    security_opt:
      - no-new-privileges:true

  controller:
    image: ghcr.io/cyr-ius/security-review:latest
    restart: unless-stopped
    # The image starts the Controller server with the `controller` command
    command: ["controller"]
    environment:
      SECREVIEW_DATABASE_URL: postgresql+psycopg2://secreview:${POSTGRES_PASSWORD}@db:5432/secreview
      # Signs the web sessions: keep the same value, or every session ends at restart
      SECREVIEW_SECRET_KEY: ${SECREVIEW_SECRET_KEY}
      # Public root URL of the controller (SECREVIEW_PUBLIC_URL=https://… in .env), copied
      # to the database at start: the mcp service gives its web interface (/ui) to the agents
      # without a token. Empty, it can be set in the web interface (General).
      SECREVIEW_PUBLIC_URL: ${SECREVIEW_PUBLIC_URL:-}
      # OAuth login of the MCP clients: the hosts sign in through the browser instead of a
      # personal MCP token (needs SECREVIEW_PUBLIC_URL in https). Behind a reverse proxy,
      # publish /.well-known/oauth-authorization-server, /authorize, /token, /register and
      # /revoke to this service, /mcp and /.well-known/oauth-protected-resource to the mcp one.
      # SECREVIEW_MCP_OAUTH_ENABLED: "true"
      # SECREVIEW_MCP_URL: https://mcp.secreview.example.com/mcp
      # Daily download of the OSV vulnerability advisories (needs Internet access)
      # SECREVIEW_OSV_AUTO_UPDATE: "true"
      # SECREVIEW_OSV_ECOSYSTEMS: PyPI,npm,Maven
      # SECREVIEW_TLS_CERTFILE: /etc/secreview/tls/cert.pem
      # SECREVIEW_TLS_KEYFILE: /etc/secreview/tls/key.pem
    # volumes:
    #   - ./tls:/etc/secreview/tls:ro
    ports:
      - "8080:8000"
    depends_on:
      db:
        condition: service_healthy
    read_only: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true

  mcp:
    image: ghcr.io/cyr-ius/security-review:latest
    restart: unless-stopped
    # The image starts the MCP server with the `mcp` command (its default): streamable HTTP on
    # /mcp (SECREVIEW_TRANSPORT)
    command: ["mcp"]
    environment:
      SECREVIEW_DATABASE_URL: postgresql+psycopg2://secreview:${POSTGRES_PASSWORD}@db:5432/secreview
      # SECREVIEW_TLS_CERTFILE: /etc/secreview/tls/cert.pem
      # SECREVIEW_TLS_KEYFILE: /etc/secreview/tls/key.pem
    # volumes:
    #   - ./tls:/etc/secreview/tls:ro
    ports:
      - "8000:8000"
    depends_on:
      # The MCP server only checks the tables: it starts once the controller has migrated them
      controller:
        condition: service_healthy
    read_only: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true

volumes:
  secreview-pg:
POSTGRES_PASSWORD=<48 caractères hexadécimaux>
SECREVIEW_SECRET_KEY=<64 caractères hexadécimaux>
Service Rôle Écoute
db PostgreSQL, joignable par les autres services seulement —
controller Interface web (/ui/) et API REST, pour les personnes ; crée ou met à jour les tables au démarrage 8080
mcp Serveur MCP (/mcp), pour les agents 8000

Bon à savoir :

  • Ordre de démarrage. controller attend que PostgreSQL soit prêt, puis crée ou met à jour les tables ; mcp, qui les vérifie seulement, attend que controller soit en bonne santé. Après une mise à jour de l'image, docker compose up -d suffit : le serveur Controller applique les nouvelles migrations.
  • Conservez .env. Il contient le mot de passe de la base et le secret des sessions ; ne le commitez jamais. Le mot de passe est inséré tel quel dans l'URL de connexion : gardez des caractères hexadécimaux, comme ci-dessus.
  • Ouvrir à l'équipe. Les ports sont publiés sur toutes les interfaces du serveur, en HTTP simple : activez le TLS intégré ou placez un reverse proxy devant avant que l'équipe se connecte. Pour garder un port sur le serveur seulement (derrière un reverse proxy sur la même machine, par exemple), préfixez-le par 127.0.0.1 ("127.0.0.1:8000:8000"). Seuls les ports décident de l'exposition : dans son conteneur, chaque processus écoute sur toutes les interfaces (SECREVIEW_HOST=0.0.0.0, fixée par l'image, à ne pas changer). Pour le TLS intégré, décommentez dans controller et mcp les variables TLS (SECREVIEW_TLS_CERTFILE, SECREVIEW_TLS_KEYFILE) et le volumes qui monte en lecture seule les fichiers du certificat depuis ./tls (voir Autorité de certification). Le serveur Controller n'expose aucune route d'écriture sans jeton : il peut rester interne, sauf si la connexion OAuth des clients MCP est active : les hôtes MCP atteignent alors ses routes OAuth (décommentez SECREVIEW_MCP_OAUTH_ENABLED et SECREVIEW_MCP_URL dans controller ; derrière un seul hôte de reverse proxy, routez /mcp et /.well-known/oauth-protected-resource vers mcp, tout le reste vers controller). Ajoutez à .env l'URL publique racine du serveur Controller (SECREVIEW_PUBLIC_URL=https://…) : le serveur Controller la recopie en base au démarrage, pour que le serveur MCP donne le lien de l'interface web (/ui) à un agent sans jeton et que les connecteurs relient leurs tickets aux rapports. Sans elle, renseignez la page Général.
  • Avis de vulnérabilités. La base OSV est vide au premier démarrage : l'analyse de dépendances répond qu'aucune base n'est chargée. Pour que le serveur Controller la télécharge au démarrage puis toutes les 24 h, décommentez SECREVIEW_OSV_AUTO_UPDATE (et SECREVIEW_OSV_ECOSYSTEMS) dans le service controller, puis lancez docker compose up -d. Suivez l'import avec docker compose logs -f controller. Sans accès Internet, importez une archive avec advisories import (voir Dépendances).
  • Durcissement. Les conteneurs de Security Review tournent en système de fichiers en lecture seule, sans capacité Linux.
  • Données. Le volume secreview-pg contient les rapports, les comptes et les jetons : sauvegardez-le (voir Sauvegarde de PostgreSQL). Il est monté sur /var/lib/postgresql, où PostgreSQL 18 range ses données ; un volume créé par PostgreSQL 17 ne démarre pas avec cette image (voir Mise à niveau de PostgreSQL).

Les commandes d'administration s'exécutent dans le conteneur du serveur Controller :

docker compose exec controller security-review-controller token list

Sans Docker Compose

La même image lance chaque processus dans son propre conteneur, sur une base PostgreSQL existante (voir Architecture) :

  • le serveur MCP se lance avec la commande mcp (par défaut), en HTTP streamable ;
  • le serveur Controller (API REST, interface web, administration) se lance avec la commande controller, avec les jetons 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. Serveur Controller : interface web et API, de préférence sur un réseau interne ; crée ou met
#    à jour le schéma (Alembic) au démarrage, donc à lancer en premier
docker run -d --name secreview-controller -p 127.0.0.1:8080:8000 \
    -e SECREVIEW_DATABASE_URL=$DB \
    ghcr.io/cyr-ius/security-review controller

# 2. 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 \
    ghcr.io/cyr-ius/security-review mcp serve --port 8443

# 3. Mot de passe du compte admin, créé au premier démarrage du serveur Controller
docker exec secreview-controller security-review-controller user reset-password admin

Dans l'image, les deux processus écoutent sur toutes les interfaces du conteneur (SECREVIEW_HOST=0.0.0.0), sur le port 8000 sauf --port : l'option -p choisit l'adresse et le port de l'hôte (-p 127.0.0.1:8080:8000 : cette machine seulement). 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é (étape 1).

Règles internes et CLI

Les règles sont stockées dans la base : importez un dossier de packs TOML avec la CLI du serveur Controller (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 \
    ghcr.io/cyr-ius/security-review controller rules import /rules

Les autres commandes passent de la même façon :

docker run --rm -v secreview-data:/var/lib/secreview \
    ghcr.io/cyr-ius/security-review controller token list