diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 0000000..830d24a --- /dev/null +++ b/README.fr.md @@ -0,0 +1,331 @@ +# docker-socket-proxy + +[English](README.md) | **Français** + +[![Docker Scout report](https://img.shields.io/badge/Docker%20Scout-view%20report-2496ED?logo=docker&logoColor=white)](https://scout.docker.com/reports/org/cerede2000/images/host/hub.docker.com/repo/cerede2000%2Fdocker-socket-proxy) + +Proxy HTTP minimaliste et sécurisé devant le socket Docker. Les clients sont associés à un profil par leur adresse IP, découverte depuis leurs labels Docker ; tout accès qui n'est pas explicitement accordé est refusé. + +Le projet permet de limiter les familles d'API Docker, puis de restreindre les opérations à certains conteneurs. Il évite ainsi de monter directement `/var/run/docker.sock` dans une application. + +## Images de production + +```text +cerede2000/docker-socket-proxy:latest +ghcr.io/cerede2000/docker-socket-proxy:latest +``` + +La première référence est publiée sur [Docker Hub](https://hub.docker.com/r/cerede2000/docker-socket-proxy) ; la seconde sur GitHub Container Registry. Les deux images sont multi-architecture (`linux/amd64` et `linux/arm64`), construites avec Go et exécutées sans privilèges dans `distroless/static-debian13:nonroot`. + +`latest` suit `main`. Chaque release Git `vX.Y.Z` publie également les tags Docker immuables `X.Y.Z` et `X.Y` sur les deux registres. + +L'image publiée est analysée en continu par [Docker Scout](https://scout.docker.com/reports/org/cerede2000/images/host/hub.docker.com/repo/cerede2000%2Fdocker-socket-proxy). Le rapport est lié ici plutôt que figé dans le README : son résultat suit les mises à jour des vulnérabilités et de l'image. + +## Ce qui le différencie + +Les socket proxies classiques limitent principalement les familles d'endpoints Docker. Celui-ci ajoute deux niveaux de contrôle complémentaires : + +1. Le droit est attribué au **client** par profil, automatiquement via son label Docker (`socketproxy.role`). +2. Le droit est ensuite limité à la **cible** : tous les conteneurs, allowlist, blacklist, refus explicite, ou accès strictement en lecture seule par conteneur. + +Un outil peut donc disposer d'un accès Docker étendu lorsque c'est nécessaire (Portainer, un opérateur), tandis que Traefik Manager peut uniquement consulter et redémarrer `traefik`. Le contrôle nom/ID est maintenu en cache et s'applique aux listes, événements et appels directs. + +## Principes de sécurité + +- Aucun droit n'est accordé implicitement. +- Seuls les conteneurs portant `socketproxy.role` (ou l'alias `socketproxy.service`) et correspondant à un profil sont autorisés. +- Le proxy ne retient que les IP partagées avec ses propres réseaux Docker. +- Les listes, les événements et les opérations ciblant un conteneur respectent la même portée. +- Le cache interne nom / ID de conteneur évite une requête Docker supplémentaire pour les vérifications usuelles. + +## Démarrage rapide + +Créez un fichier `profiles.yml`, puis lancez le proxy. Le montage du socket est en lecture seule : les requêtes Docker restent possibles via l'API Unix, mais le fichier socket ne peut pas être remplacé depuis le conteneur. + +```yaml +services: + docker-socket-proxy: + image: cerede2000/docker-socket-proxy:latest + container_name: docker-socket-proxy + user: "1000:998" # adapter à l'UID:GID pouvant lire le socket sur l'hôte + read_only: true + cap_drop: [ALL] + security_opt: + - no-new-privileges:true + tmpfs: + - /tmp + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./profiles.yml:/config/profiles.yml:ro + networks: + - socketproxy + restart: unless-stopped + +networks: + socketproxy: + internal: true +``` + +Le compte configuré avec `user` doit avoir accès au socket Docker de l'hôte. Vérifiez son UID et son GID avec `stat -c '%u:%g' /var/run/docker.sock` sous Linux, puis adaptez la valeur. Sur certaines installations, il est préférable de construire une image dérivée qui crée un groupe portant le GID réel du socket. + +## Associer un client à un profil + +Ajoutez l'un des deux labels suivants au conteneur client : + +```yaml +labels: + socketproxy.role: mon-profil + # ou : socketproxy.service: mon-profil +``` + +Le profil est rechargé automatiquement lorsque `profiles.yml` est modifié. La découverte des IP intervient au démarrage, lors des événements Docker pertinents, et périodiquement. + +## Exemple complet : Traefik et Traefik Manager + +Cet exemple sépare les rôles : Traefik peut lire les informations nécessaires au provider Docker ; Traefik Manager peut seulement consulter et redémarrer le conteneur `traefik`. Il ne peut ni agir sur les autres conteneurs ni lancer d'exec. + +`compose.yml` : + +```yaml +services: + docker-socket-proxy: + image: cerede2000/docker-socket-proxy:latest + container_name: docker-socket-proxy + user: "1000:998" # à adapter à l'hôte + read_only: true + cap_drop: [ALL] + security_opt: + - no-new-privileges:true + tmpfs: + - /tmp + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./profiles.yml:/config/profiles.yml:ro + networks: [socketproxy] + restart: unless-stopped + + traefik: + image: traefik:v3 + container_name: traefik + command: + - --providers.docker=true + - --providers.docker.endpoint=tcp://docker-socket-proxy:2375 + - --providers.docker.exposedbydefault=false + labels: + socketproxy.role: traefik + networks: [socketproxy, frontend] + restart: unless-stopped + + traefik-manager: + image: ghcr.io/chr0nzz/traefik-manager:latest + container_name: traefik-manager + environment: + DOCKER_HOST: tcp://docker-socket-proxy:2375 + RESTART_METHOD: proxy + TRAEFIK_CONTAINER: traefik + labels: + socketproxy.role: traefik-manager + networks: [socketproxy, frontend] + restart: unless-stopped + +networks: + socketproxy: + internal: true + frontend: + external: true +``` + +`profiles.yml` : + +```yaml +traefik: + ping: true + version: true + containers: true + networks: true + events: true + session: true + +traefik-manager: + ping: true + version: true + containers: true + post: true + allow_restart: true + container_scope: allowlist + allowed_containers: + - traefik +``` + +`container_name: traefik` et `allowed_containers: [traefik]` doivent correspondre exactement. Le profil `traefik-manager` ne permet pas `start` ou `stop` : seul `POST /containers/traefik/restart` est admis. + +## Configuration du proxy + +| Variable | Défaut | Description | +| --- | --- | --- | +| `DOCKER_SOCKET_PATH` | `/var/run/docker.sock` | Chemin du socket Docker à joindre | +| `PROXY_PORT` | `2375` | Port d'écoute et port du healthcheck intégré | +| `PROXY_LISTEN` | — | Adresse d'écoute complète ; prioritaire sur `PROXY_PORT` | +| `SOCKETPROXY_PROFILE_FILE` | `/config/profiles.yml` | Fichier YAML des profils | +| `DISCOVER_INTERVAL` | `30s` | Période de redécouverte des conteneurs ; durée Go (`15s`) ou nombre de secondes (`15`) | +| `EVENT_DEBOUNCE_DELAY` | `100ms` | Délai de regroupement des événements Docker ; durée Go ou nombre de millisecondes | + +Les arguments suivants sont disponibles et prioritaires sur les variables correspondantes : `--listen`, `--socket`, `--profiles`, `--discover-interval` et `--debounce-delay`. + +Le healthcheck appelle `http://127.0.0.1:$PROXY_PORT/version`. Si `--listen` ou `PROXY_LISTEN` utilise un autre port, renseignez `PROXY_PORT` avec ce même port. + +### Options de ligne de commande par profil + +Les profils peuvent aussi être définis dans la commande du conteneur. Le format est `--.