From 32edb96b408fe65366fe38bbc411e0f84595a37f Mon Sep 17 00:00:00 2001 From: bisco Date: Thu, 25 Jun 2026 12:53:36 +0200 Subject: [PATCH] fix: make wordpress healthcheck production safe --- docker-compose.yml | 2 +- docs/runbook.md | 17 +++++++++++++++++ wordpress/Dockerfile | 2 ++ wordpress/healthcheck.php | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 wordpress/healthcheck.php diff --git a/docker-compose.yml b/docker-compose.yml index 6e5ded2..f8ee75c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -73,7 +73,7 @@ services: db: condition: service_healthy healthcheck: - test: ["CMD", "php", "-r", "$$c=@file_get_contents('http://127.0.0.1/wp-login.php'); exit($$c===false ? 1 : 0);"] + test: ["CMD", "php", "/usr/local/bin/azionelab-healthcheck.php"] interval: 10s timeout: 5s retries: 20 diff --git a/docs/runbook.md b/docs/runbook.md index bfc6e7c..7a39933 100644 --- a/docs/runbook.md +++ b/docs/runbook.md @@ -6,6 +6,23 @@ 2. Run `docker compose --profile tools run --rm wp-cli /scripts/bootstrap.sh`. 3. Inspect `docker compose logs wordpress db` without printing secret values. +## WordPress stays in waiting or unhealthy + +1. Inspect `docker compose logs wordpress db` without printing secret values. +2. Confirm the database volume was initialized with the same `MARIADB_DATABASE`, + `MARIADB_USER`, and password currently configured in `.env`. +3. Confirm `WP_URL` has the intended scheme and hostname. In production it should be + the public HTTPS URL. +4. Rebuild after changes to the WordPress image: + + ```bash + docker compose up --build -d wordpress + ``` + +The WordPress healthcheck is internal and does not depend on the public DNS/TLS route. +It sends the configured host and forwarded protocol headers to avoid following external +HTTPS redirects during production startup. + ## NGINX returns 502 1. Run `docker compose ps` and `docker compose exec proxy nginx -t`. diff --git a/wordpress/Dockerfile b/wordpress/Dockerfile index a346b82..40835de 100644 --- a/wordpress/Dockerfile +++ b/wordpress/Dockerfile @@ -3,11 +3,13 @@ FROM wordpress:7.0.0-php8.3-apache COPY php.ini /usr/local/etc/php/conf.d/azionelab.ini COPY .htaccess /opt/azionelab/.htaccess COPY entrypoint-wrapper.sh /usr/local/bin/azionelab-entrypoint +COPY healthcheck.php /usr/local/bin/azionelab-healthcheck.php COPY theme/azionelab /opt/azionelab/theme COPY mu-plugins/azionelab-content.php /opt/azionelab/azionelab-content.php RUN sed -ri 's!^[[:space:]]*CustomLog .*!CustomLog /dev/null combined!' /etc/apache2/sites-available/000-default.conf \ && chmod 755 /usr/local/bin/azionelab-entrypoint \ + && chmod 644 /usr/local/bin/azionelab-healthcheck.php \ && chown -R www-data:www-data /opt/azionelab ENTRYPOINT ["azionelab-entrypoint"] diff --git a/wordpress/healthcheck.php b/wordpress/healthcheck.php new file mode 100644 index 0000000..1516165 --- /dev/null +++ b/wordpress/healthcheck.php @@ -0,0 +1,36 @@ + [ + 'follow_location' => 0, + 'header' => "Host: {$hostHeader}\r\nX-Forwarded-Proto: {$scheme}\r\n", + 'ignore_errors' => true, + 'max_redirects' => 0, + 'timeout' => 3, + ], +]); + +$response = @file_get_contents('http://127.0.0.1/wp-login.php', false, $context); +if ($response === false || empty($http_response_header[0])) { + exit(1); +} + +if (!preg_match('/\s([0-9]{3})\s/', $http_response_header[0], $matches)) { + exit(1); +} + +$status = (int) $matches[1]; +exit($status >= 200 && $status < 400 ? 0 : 1);