From d9890cfb5d3eced5c035d859d7c10b8a92e47e94 Mon Sep 17 00:00:00 2001 From: Imugiii Date: Thu, 30 Apr 2026 11:36:10 +0000 Subject: [PATCH] chore(docker): smoke test fixes for stack startup and healthz Three issues surfaced when running 'make init' on the deployment host and were fixed in place: - wakdo_internal network: explicit subnet 192.168.148.0/24 (RFC 1918, in the free 192.168.144-159 gap). The host's Docker daemon has its default address pools saturated by other stacks, so auto-allocation failed. An explicit subnet bypasses the allocator and isolates Wakdo from neighbour churn. - wakdo-cron: init: true added so Docker injects tini as PID 1. Without it, dcron loops on 'setpgid: Operation not permitted' because PID 1 in a container without an init system cannot change process groups for its children. - healthz vhost: served as a static file from /usr/local/apache2/htdocs/ instead of a RewriteRule [R=200] that triggered Apache's ErrorDocument template (and leaked 'internal error' wording into a 200 response). The file lives outside /var/www/html/ which is bind-mounted at runtime and would otherwise mask the COPY. --- docker-compose.yml | 17 +++++++++++++++++ docker/apache/Dockerfile | 9 +++++++++ docker/apache/healthz.txt | 1 + docker/apache/vhost.conf | 22 +++++++++++++--------- 4 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 docker/apache/healthz.txt diff --git a/docker-compose.yml b/docker-compose.yml index 945c1aa..d131af4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,6 +38,18 @@ networks: # de sortir sur internet (pour telecharger des packages au build et pour # de potentiels appels API externes futurs). L'isolation vient du fait # qu'aucun port hote n'est binde ici. + # + # Subnet explicite (RFC 1918) : l'auto-allocateur Docker du daemon hote + # est sature (15 /16 + 15 /20 deja alloues par d'autres stacks), il ne + # peut plus creer de reseau bridge sans subnet explicite. 192.168.148.0/24 + # est dans le gap libre 192.168.144-159 (256 IP, largement suffisant pour + # 4 services), aucune collision avec les /24 acquagest voisins (150/154/ + # 155/157). Choix defendable : right-sizing + isolation des fluctuations + # d'allocation auto sur cet hote mutualise. + ipam: + driver: default + config: + - subnet: 192.168.148.0/24 # Reseau du reverse proxy (Traefik) pre-existant sur l'hote. # Son nom est configurable via REVERSE_PROXY_NETWORK dans .env pour @@ -222,6 +234,11 @@ services: dockerfile: Dockerfile container_name: wakdo-cron restart: unless-stopped + # init: true -> Docker injecte tini comme PID 1. dcron exige un init + # parent pour pouvoir setpgid() sur ses jobs (sinon "Operation not + # permitted" en boucle car un PID 1 sans init ne peut pas changer les + # groupes de processus). Cf. busybox-utils issue tracker. + init: true environment: # Credentials BDD pour mysqldump (lecture seule via USER applicatif, diff --git a/docker/apache/Dockerfile b/docker/apache/Dockerfile index d9ae42c..abbed7b 100644 --- a/docker/apache/Dockerfile +++ b/docker/apache/Dockerfile @@ -27,6 +27,15 @@ COPY mpm.conf /usr/local/apache2/conf/extra/wakdo-mpm.conf # bind-mounte en dev. Sans ca, Apache refuse de demarrer. RUN mkdir -p /var/www/html/public +# Fichier statique servi par le vhost healthz (Alias /healthz). Evite +# le RewriteRule [R=200] qui declenche le template ErrorDocument d'Apache +# et pollue le body de la reponse. +# Place dans /usr/local/apache2/htdocs/ et non /var/www/html/ : ce dernier +# est bind-monte depuis ./src au runtime (cf. docker-compose.yml), ce qui +# masquerait le fichier copie ici. /usr/local/apache2/htdocs/ est un chemin +# Apache natif jamais bind-monte. +COPY healthz.txt /usr/local/apache2/htdocs/healthz.txt + # Healthcheck : vhost par defaut (0.0.0.0:80) doit repondre. # Le endpoint /healthz est defini dans vhost.conf, repond 200 "ok". HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ diff --git a/docker/apache/healthz.txt b/docker/apache/healthz.txt new file mode 100644 index 0000000..d86bac9 --- /dev/null +++ b/docker/apache/healthz.txt @@ -0,0 +1 @@ +OK diff --git a/docker/apache/vhost.conf b/docker/apache/vhost.conf index 40b6be3..469e57c 100644 --- a/docker/apache/vhost.conf +++ b/docker/apache/vhost.conf @@ -16,21 +16,25 @@ # === Healthcheck interne Docker (non expose publiquement) === # Listen sans ServerName = catch-all. Utilise par le HEALTHCHECK du Dockerfile. +# Sert un fichier statique healthz.txt (body = "OK\n") au lieu d'un +# RewriteRule [R=200] qui declenchait le template ErrorDocument generique +# et faisait apparaitre la mention "internal error" dans le body d'un 200. +# Le fichier vit dans /usr/local/apache2/htdocs/ (chemin Apache natif, jamais +# bind-monte) et non dans /var/www/html/ qui est ecrase par le bind-mount +# ./src au runtime. - DocumentRoot "/var/www/html/public" + DocumentRoot "/usr/local/apache2/htdocs" - - SetHandler none - Require all granted - + Alias /healthz /usr/local/apache2/htdocs/healthz.txt - Alias /healthz /dev/null - + Require all granted - RewriteEngine On - RewriteRule ^/healthz$ - [R=200,L] + + # Pas de cache : la sonde doit toujours toucher Apache. + Header set Cache-Control "no-store" + # === Borne client (Bloc 1 - front vanilla HTML/CSS/JS) ===