Aller au contenu

Réseau et domaines

PerfShop fonctionne sur un réseau Docker bridge unique nommé perfshop-network, qui isole les communications entre les 31 services et permet la résolution DNS par nom de container. Côté hôte, chaque service applicatif expose son port via le mapping standard "<port_hôte>:<port_container>" configuré par les variables d'environnement.

Cette page décrit :

  1. La topologie du réseau Docker interne
  2. La table complète des ports exposés à l'hôte
  3. Les conventions de communication inter-services
  4. Le pattern de reverse proxy externe pour exposer la stack en HTTPS

Source de vérité

Les ports, les noms de services et les variables d'environnement de cette page sont extraits des fichiers docker-compose.desktop.yml et docker-compose.build.yml. Les conventions DNS publiques sont déduites des variables PUBLIC_*_URL du .env.example.

Topologie du réseau Docker

flowchart TB
  subgraph host["Hôte (poste ou VPS)"]
    rp{"Reverse proxy externe<br/>(optionnel)<br/>nginx, Caddy, Traefik..."}

    subgraph engine["Docker Engine"]
      subgraph bridge["perfshop-network (bridge)"]
        direction TB

        subgraph c["Cœur"]
          DB[("perfshop-db<br/>:3306")]
          APP["perfshop-app<br/>:8080 + :9090"]
          FE["perfshop-frontend<br/>:80"]
          MON["perfshop-monitoring<br/>:3001"]
          ADM["perfshop-admin<br/>:80"]
          CADM["perfshop-chaos-admin<br/>:80"]
          WC["perfshop-welcome<br/>:3011"]
          DOC["docs<br/>:8000"]
        end

        subgraph o["Observabilité"]
          PROM["prometheus<br/>:9090"]
          GRAF["grafana<br/>:3000"]
          LOKI["perfshop-loki<br/>:3100"]
          PT["perfshop-promtail"]
          TEMPO["perfshop-tempo<br/>:3200/:4317/:4318"]
          PYRO["perfshop-pyroscope<br/>:4040"]
          OS["perfshop-opensearch<br/>:9200"]
          OSD["perfshop-opensearch-dashboards<br/>:5601"]
          VEC["perfshop-vector"]
        end

        subgraph q["QA"]
          JM["perfshop-jmeter"]
          JMUI["perfshop-jmeter-ui<br/>:3005"]
          SQDB[("perfshop-squash-db<br/>:5432")]
          STM["perfshop-testmgmt<br/>:8080"]
          ORCH["perfshop-orchestrator"]
          SEL["perfshop-selenium<br/>:4444 + :7900"]
          TR["perfshop-test-runner<br/>:22"]
          FG["perfshop-forgejo<br/>:3000"]
          SUI["perfshop-scripts-ui<br/>:3008"]
        end
      end
    end

    rp -->|HTTPS terminating| bridge
  end

  user["Navigateur"] -->|HTTPS| rp
  user -.-|HTTP direct si pas de reverse proxy| bridge

Caractéristiques :

  • Pilote bridge standard : aucun mode host ou macvlan. Tous les containers ont une IP privée allouée par Docker dans le sous-réseau du bridge.
  • DNS interne automatique : chaque container est joignable par les autres via son container_name (qui correspond au nom du service Compose). Exemple : perfshop-app peut atteindre la BDD via jdbc:mysql://perfshop-db:3306/perfshop.
  • Pas de communication directe entre hôtes : la stack est mono-hôte. Aucun discovery cluster, aucun service mesh.
  • Tous les services partagent le même réseau : c'est volontaire. Aucune segmentation réseau interne entre les groupes (cœur / obs / QA) — la séparation est logique, pas réseau.

Ports exposés à l'hôte

Tous les ports sont configurables via les variables d'environnement listées en colonne de droite. Les valeurs par défaut sont celles du fichier .env.example.

Service Port hôte Port container Variable d'env Usage
perfshop-db 19306 3306 DB_PORT Connexion MySQL externe (debug) — ⚠️ port 3306 réservé par Hyper-V/WSL2
perfshop-app 8080 8080 BACKEND_HTTP_PORT API REST principale
perfshop-app 9090 9090 BACKEND_METRICS_PORT Spring Boot Actuator (/actuator/prometheus, /actuator/health, /actuator/heapdump)
perfshop-frontend 8090 80 FRONTEND_HTTP_PORT Boutique React (nginx)
perfshop-monitoring 3001 3001 MONITORING_HTTP_PORT Dashboard temps réel HTML
perfshop-admin 3004 80 ADMIN_HTTP_PORT Backoffice produits/commandes
perfshop-chaos-admin 3003 80 CHAOS_HTTP_PORT Pilotage des chaos
perfshop-welcome 3011 3011 (figé) Page d'annuaire
docs 8087 8000 DOCS_HTTP_PORT Documentation MkDocs
prometheus 9091 9090 PROMETHEUS_HTTP_PORT UI Prometheus + endpoint scrape
grafana 3002 3000 GRAFANA_HTTP_PORT UI Grafana
perfshop-loki 19100 3100 LOKI_HTTP_PORT API Loki (push + query) — ⚠️ port 3100 réservé par Hyper-V/WSL2
perfshop-tempo 19200 3200 TEMPO_HTTP_PORT API HTTP query Tempo — ⚠️ port 3200 réservé par Hyper-V/WSL2
perfshop-tempo 4317 4317 TEMPO_OTLP_GRPC_PORT OTLP gRPC (export traces depuis l'agent Java)
perfshop-tempo 4318 4318 TEMPO_OTLP_HTTP_PORT OTLP HTTP (alternative)
perfshop-pyroscope 4040 4040 PYROSCOPE_HTTP_PORT API Pyroscope (push + query)
perfshop-opensearch 9201 9200 OPENSEARCH_API_PORT API REST OpenSearch
perfshop-opensearch-dashboards 5601 5601 OPENSEARCH_HTTP_PORT UI OpenSearch Dashboards
perfshop-jmeter-ui 3005 3005 JMETER_UI_PORT UI custom JMeter
perfshop-squash-db 5433 5432 SQUASH_DB_PORT PostgreSQL Squash (debug)
perfshop-testmgmt 8088 8080 SQUASH_HTTP_PORT Squash TM
perfshop-selenium 4444 4444 SELENIUM_HTTP_PORT Selenium WebDriver
perfshop-selenium 7900 7900 SELENIUM_VNC_PORT noVNC (debug visuel des sessions Chrome)
perfshop-forgejo 3009 3000 FORGEJO_HTTP_PORT UI Forgejo + API REST
perfshop-scripts-ui 3008 3008 SCRIPTS_UI_PORT UI Scripts

Conflits de ports

Si l'un de ces ports par défaut est déjà occupé sur la machine hôte (par exemple 3306 pour une autre instance MySQL), il suffit de surcharger la variable correspondante dans le .env. Toutes les références internes utilisent les noms DNS Docker, donc ces variables n'impactent que le mapping côté hôte.

Communication inter-services (DNS Docker)

Les services se parlent par nom de container, jamais par IP. Voici les principales chaînes de communication.

Backend → BDD et observabilité

flowchart LR
  APP["perfshop-app"]
  DB[("perfshop-db:3306")]
  TEMPO["perfshop-tempo:4317<br/>(OTLP gRPC)"]
  PYRO["perfshop-pyroscope:4040<br/>(JFR push)"]

  APP -->|jdbc:mysql://perfshop-db:3306/perfshop| DB
  APP -->|OTLP gRPC| TEMPO
  APP -->|JFR HTTP push| PYRO

Prometheus → cibles scrapées

flowchart LR
  PROM["prometheus"]
  APP["perfshop-app:9090<br/>/actuator/prometheus"]
  MON["perfshop-monitoring:3001<br/>/metrics"]
  JM["perfshop-jmeter:9270<br/>(actif pendant un tir)"]

  PROM -->|scrape 5s| APP
  PROM -->|scrape 5s| MON
  PROM -->|scrape 5s| JM

Grafana → datasources

flowchart LR
  GRAF["grafana"]
  PROM["http://prometheus:9090"]
  LOKI["http://perfshop-loki:3100"]
  TEMPO["http://perfshop-tempo:3200"]
  PYRO["http://perfshop-pyroscope:4040"]

  GRAF --> PROM
  GRAF --> LOKI
  GRAF --> TEMPO
  GRAF --> PYRO

Frontend / admin / chaos-admin → backend

Toutes les UIs HTML/JS appellent le backend depuis le navigateur (origines cross-domain), donc :

  • L'URL appelée est l'URL publique du backend (variable PUBLIC_API_URL, ex. http://localhost:8080 ou https://perfshop-api.example.com).
  • Le backend autorise ces origines via CORS_ALLOWED_ORIGINS calculée dynamiquement à partir des variables PUBLIC_*_URL.
  • Le frontend nginx n'agit pas comme un proxy vers le backend : il sert uniquement les fichiers statiques. Les appels API se font directement depuis le navigateur vers perfshop-app.
flowchart LR
  B["Navigateur<br/>Étudiant"]
  FE["perfshop-frontend<br/>(HTML/JS statiques)"]
  BE["perfshop-app<br/>(API REST)"]

  B -->|GET /index.html| FE
  FE -->|charge bundle JS| B
  B -->|fetch '/api/products'| BE

  style FE fill:#fff,stroke:#888
  style BE fill:#fff,stroke:#888

Stack QA — chaînes de pilotage

flowchart LR
  SUI["perfshop-scripts-ui"]
  FG["perfshop-forgejo:3000"]
  TR["perfshop-test-runner:22<br/>(SSH)"]
  SEL["perfshop-selenium:4444"]
  STM["perfshop-testmgmt:8080"]
  ORCH["perfshop-orchestrator"]

  SUI -->|push Git API| FG
  SUI -->|docker exec via socket| TR
  TR -->|WebDriver| SEL

  STM -->|polling SCM| FG
  ORCH -->|REST| STM
  ORCH -->|SSH avec clé pubique| TR
  TR -->|WebDriver| SEL

JMeter UI → JMeter container

perfshop-jmeter-ui n'utilise pas la résolution DNS pour piloter JMeter : il monte le socket Docker (/var/run/docker.sock) et exécute docker exec perfshop-jmeter .... C'est un canal de contrôle hors réseau, qui permet de lancer les tirs sans avoir à exposer un serveur de contrôle JMeter.

flowchart LR
  JMUI["perfshop-jmeter-ui<br/>(node.js)"]
  SOCK["/var/run/docker.sock"]
  JM["perfshop-jmeter<br/>(idle, tail -f /dev/null)"]

  JMUI -->|monte| SOCK
  SOCK -.->|docker exec<br/>jmeter -n -t ...| JM

Reverse proxy externe (HTTPS public)

Pour exposer PerfShop publiquement (formation hébergée, démo cliente), on place un reverse proxy externe devant la stack. PerfShop ne fournit pas ce reverse proxy : c'est à l'opérateur d'installer et de configurer nginx, Caddy, Traefik, HAProxy, ou tout autre.

Pattern recommandé

flowchart LR
  internet["Étudiants<br/>(navigateur)"]
  rp["Reverse proxy<br/>(nginx / Caddy / Traefik)<br/>:443 HTTPS"]
  net["perfshop-network<br/>(ports HTTP locaux)"]

  internet -->|"shop.example.com"| rp
  internet -->|"api.example.com"| rp
  internet -->|"grafana.example.com"| rp

  rp -->|"http://127.0.0.1:8090"| net
  rp -->|"http://127.0.0.1:8080"| net
  rp -->|"http://127.0.0.1:3002"| net

Conventions de sous-domaines

Si on souhaite suivre une convention cohérente, la nomenclature utilisée par les variables PUBLIC_*_URL du .env.example propose :

Variable Sous-domaine type Cible interne
PUBLIC_FRONTEND_URL shop.<domaine> perfshop-frontend:80 (port hôte 8090)
PUBLIC_API_URL api.<domaine> perfshop-app:8080 (port hôte 8080)
PUBLIC_MONITORING_URL monitoring.<domaine> perfshop-monitoring:3001
PUBLIC_GRAFANA_URL grafana.<domaine> grafana:3000 (port hôte 3002)
PUBLIC_CHAOS_URL chaos.<domaine> perfshop-chaos-admin:80 (port hôte 3003)
PUBLIC_ADMIN_URL admin.<domaine> perfshop-admin:80 (port hôte 3004)
PUBLIC_DOCS_URL docs.<domaine> docs:8000 (port hôte 8087)
PUBLIC_JMETER_URL jmeter.<domaine> perfshop-jmeter-ui:3005
PUBLIC_SCRIPTS_URL scripts.<domaine> perfshop-scripts-ui:3008
PUBLIC_FORGEJO_URL git.<domaine> perfshop-forgejo:3000 (port hôte 3009)
PUBLIC_OPENSEARCH_URL logs.<domaine> perfshop-opensearch-dashboards:5601
PUBLIC_SQUASH_URL squash.<domaine> perfshop-testmgmt:8080 (port hôte 8088)
PUBLIC_SELENIUM_VNC_URL vnc.<domaine> perfshop-selenium:7900

WebSockets et SSE

Plusieurs services utilisent des WebSockets ou des Server-Sent Events (Squash TM, noVNC, OpenSearch Dashboards, Forgejo en édition de fichiers). Le reverse proxy doit explicitement supporter Upgrade: websocket et désactiver le buffering pour ces routes.

Propagation aux services

Une fois les PUBLIC_*_URL posées dans le .env, elles sont propagées automatiquement :

  • Backend : CORS_ALLOWED_ORIGINS est composée à partir de PUBLIC_FRONTEND_URL, PUBLIC_MONITORING_URL, PUBLIC_CHAOS_URL, PUBLIC_ADMIN_URL. C'est ce qui autorise le frontend hébergé sur shop.example.com à appeler api.example.com.
  • Frontend React : VITE_API_URL, VITE_MONITORING_URL sont substituées dans les fichiers JS bundlés au démarrage du container nginx via le script env-inject.sh.
  • Monitoring Node : reçoit toutes les PUBLIC_*_URL et les injecte dans window.__CONFIG__ côté navigateur (cf. monitoring/src/server.js).
  • Welcome page : toutes les PUBLIC_*_URL sont consommées pour générer l'annuaire de liens.
  • Grafana : GF_SERVER_ROOT_URL est positionnée à PUBLIC_GRAFANA_URL pour que les liens absolus dans les emails et l'API soient corrects.

Adresses internes et externes — récapitulatif

Contexte URL utilisée Exemple
Container → container (interne au bridge) http://<service>:<port_container> http://perfshop-app:8080, http://perfshop-loki:3100
Navigateur → service (sans reverse proxy) http://<host>:<port_hôte> http://localhost:8080, http://192.168.1.10:3002
Navigateur → service (avec reverse proxy) https://<sous-domaine>.<domaine> https://api.example.com, https://grafana.example.com
Backend → autre backend toujours nom de container jdbc:mysql://perfshop-db:3306/perfshop
Agent Java → Tempo / Pyroscope nom de container http://perfshop-tempo:4317, http://perfshop-pyroscope:4040

C'est la séparation explicite entre URLs publiques et URLs internes qui rend la stack portable : on peut migrer la même configuration entre Docker Desktop, un VPS Linux et n'importe quel reverse proxy externe sans toucher au code applicatif, simplement en ajustant les variables PUBLIC_*_URL.

Pour aller plus loin