fix(ubuntu-php): get the Ubuntu PHP images working, and gate them #41

Open
geusebio wants to merge 4 commits from claude/nervous-sinoussi-ff5f90 into main
Owner

The ubuntu-php assertions were commented out in test.yml, and the ubuntu-php healthchecks in test-healthchecks.yml, because the images could not pass validation. Reported symptom:

Nginx version 1.24 does not match expected version 1.28
Validation failed for /etc/validate.d/nginx.sh

That was accurate, but it was the first of five faults. The nginx version alone would not have let either gate be re-enabled.

The last two only became visible once the images were run rather than merely built — which is what the disabled healthchecks were hiding, and why 8.x had been shipping with no PHP extensions and a dead web server for as long as it had.


1. nginx version recorded as 1.28 on a base that ships 1.24

All five stages build FROM ./Ubuntu.Dockerfile#ubuntu-24-base, and noble ships 1.24.0-2ubuntu7.15. The ondrej/php PPA, added before nginx installs, does not bump it.

Set to 1.24 rather than adding nginx.org. NGINX_VERSION is descriptive, not prescriptive — it feeds the ooo.grey.version.nginx label and the assertion, and selects nothing. PHP.Dockerfile already varies it per base (1.28 / 1.24 / 1.20) to match what each Alpine ships, so Alpine running 1.28 is what its repo happens to provide rather than a target being pursued. Sourcing from nginx.org would mean a third-party repo and signing key, and would make Ubuntu the only image bypassing its distro.

2. No PHP extensions loaded on any 8.x image

The shared fs/php-nginx overlay uses Alpine's flat /etc/php, which works there only because ln -s /etc/php /etc/php${PHP_VER} covers the one path PHP reads. Ondrej compiles in /etc/php/<version>/{cli,fpm}inside /etc/php, where that symlink cannot reach — so conf.d was never scanned.

FIX_PERMS reshaped the tree only under if [[ "$PHP_VER" -eq 7 ]], leaving every 8.x image on its built-ins alone: 18 modules while 51 .so files sat unused.

Now linked for all versions, and as symlinks rather than the copies the 7.4 branch used — those copies meant the runtime toggles in services.d/php/run, which rewrite /etc/php/conf.d, were editing files PHP never read. That branch is now just the pm.max_spawn_rate fixup it was documented to be.

image modules before modules after
ubuntu-php-84 18 65
ubuntu-php-74 warning spam 63, clean

3. Startup warnings on stdout

Once conf.d was scanned, PHP warned about every extension ondrej builds in (openssl, pcntl, session, sodium) or omits (gmp, odbc, snmp, tidy, ...). Those ini files can never load, so they are pruned.

The remaining warning — opcache disabling JIT because xdebug overrides zend_execute_ex() — is legitimate. It broke validation only because php.sh read php --version | head -n 1 and PHP prints startup warnings to stdout, so the parse landed on a warning. It now selects the version line.

That warning also went to stdout on every CLI call, which would corrupt any script being piped. Of the settings that suppress it, only opcache.enable_cli is CLI-scoped: opcache.jit and jit_buffer_size live in the shared conf.d and would cost FPM its JIT, and display_errors there would silently override the PHP_DISPLAY_ERRORS tunable, since conf.d is scanned after php.ini. JIT is inert beside xdebug anyway and a CLI process is too short-lived for the opcode cache, so it is off for the CLI only.

4. The CLI never loaded php.ini

Ondrej looks for it at /etc/php/<version>/cli/, and only FPM was covered, by the explicit php-fpm -c /etc/php/ in the service script. So composer and every docker run <img> php ... quietly used upstream defaults instead of the tuned config. Now linked for both SAPIs: memory_limit reads 128M from php.ini, expose_php is Off.

5. nginx had never started

The overlay's nginx.conf includes /etc/nginx/mime.types, which only the distro package provides, but INSTALL_PHP removed /etc/nginx wholesale. Alpine removes only /etc/php*, which is why it never showed there. nginx crash-looped:

open() "/etc/nginx/mime.types" failed (2: No such file or directory) in /etc/nginx/nginx.conf:18

Only Ubuntu's own vhost wiring is removed now. The 7.4 healthcheck block also carried a mis-indented configs: that would not have parsed.


Interaction with main

Merged origin/main, which lands pcov (#37) on these images. The two changes reinforce each other rather than collide:

  • pcov is packaged for Ubuntu, so pcov.so is on disk and the prune correctly keeps 51_pcov.ini. pcov loads with pcov.enabled='0', and php.sh reports "pcov present and correctly disabled by default: OK".
  • main's new check reads $(php -r 'echo ini_get("pcov.enabled") ? "on" : "";') and fails if non-empty. On Ubuntu 8.x that would have captured the JIT warning and falsely reported "pcov is enabled by default" — fix 3 is what makes it pass.
  • main's 51_pcov.ini documents that correct coverage requires opcache.enable_cli=0, calling it a correctness requirement that fails silently. Fix 3 makes that the Ubuntu default.

Verification

All five assertions and all five healthchecks pass, and are wired into the aggregator. The healthchecks were checked beyond the health flag: HTTP 200, 98KB phpinfo, PHP 8.4.24, zero nginx errors.

fs/php-nginx/etc/validate.d/php.sh is shared, so the other families were re-verified: php-85, php-83, php-74, magento-php-85, php-85-node, frankenphp-85 all pass. frankenphp carries its own copy and is untouched.

Still out of scope

  • fs/php-frankenphp/etc/validate.d/php.sh keeps the same fragile head -n 1. It passes today, so the duplication is left rather than changing a file with no failing case.
  • tea cannot operate on this repo at all — its git library rejects it with core.repositoryformatversion does not support extension: worktreeconfig, from both a worktree and the main checkout. This PR and its comments were made through the Forgejo API. CLAUDE.md directs PR work through tea, so that instruction will fail for anyone with the same config.

🤖 Generated with Claude Code

The `ubuntu-php` assertions were commented out in `test.yml`, and the `ubuntu-php` healthchecks in `test-healthchecks.yml`, because the images could not pass validation. Reported symptom: ``` Nginx version 1.24 does not match expected version 1.28 Validation failed for /etc/validate.d/nginx.sh ``` That was accurate, but it was the first of **five** faults. The nginx version alone would not have let either gate be re-enabled. The last two only became visible once the images were *run* rather than merely built — which is what the disabled healthchecks were hiding, and why 8.x had been shipping with no PHP extensions and a dead web server for as long as it had. --- ### 1. nginx version recorded as 1.28 on a base that ships 1.24 All five stages build `FROM ./Ubuntu.Dockerfile#ubuntu-24-base`, and noble ships `1.24.0-2ubuntu7.15`. The `ondrej/php` PPA, added *before* nginx installs, does not bump it. Set to `1.24` rather than adding nginx.org. `NGINX_VERSION` is descriptive, not prescriptive — it feeds the `ooo.grey.version.nginx` label and the assertion, and selects nothing. `PHP.Dockerfile` already varies it per base (1.28 / 1.24 / 1.20) to match what each Alpine ships, so Alpine running 1.28 is what its repo happens to provide rather than a target being pursued. Sourcing from nginx.org would mean a third-party repo and signing key, and would make Ubuntu the only image bypassing its distro. ### 2. No PHP extensions loaded on any 8.x image The shared `fs/php-nginx` overlay uses Alpine's flat `/etc/php`, which works there only because `ln -s /etc/php /etc/php${PHP_VER}` covers the one path PHP reads. Ondrej compiles in `/etc/php/<version>/{cli,fpm}` — *inside* `/etc/php`, where that symlink cannot reach — so `conf.d` was never scanned. `FIX_PERMS` reshaped the tree only under `if [[ "$PHP_VER" -eq 7 ]]`, leaving every 8.x image on its built-ins alone: **18 modules while 51 `.so` files sat unused**. Now linked for all versions, and as symlinks rather than the copies the 7.4 branch used — those copies meant the runtime toggles in `services.d/php/run`, which rewrite `/etc/php/conf.d`, were editing files PHP never read. That branch is now just the `pm.max_spawn_rate` fixup it was documented to be. | image | modules before | modules after | |---|---|---| | `ubuntu-php-84` | 18 | **65** | | `ubuntu-php-74` | warning spam | **63**, clean | ### 3. Startup warnings on stdout Once `conf.d` was scanned, PHP warned about every extension ondrej builds in (`openssl`, `pcntl`, `session`, `sodium`) or omits (`gmp`, `odbc`, `snmp`, `tidy`, ...). Those ini files can never load, so they are pruned. The remaining warning — opcache disabling JIT because xdebug overrides `zend_execute_ex()` — is legitimate. It broke validation only because `php.sh` read `php --version | head -n 1` and PHP prints startup warnings to **stdout**, so the parse landed on a warning. It now selects the version line. That warning also went to stdout on every CLI call, which would corrupt any script being piped. Of the settings that suppress it, only `opcache.enable_cli` is CLI-scoped: `opcache.jit` and `jit_buffer_size` live in the shared `conf.d` and would cost **FPM** its JIT, and `display_errors` there would silently override the `PHP_DISPLAY_ERRORS` tunable, since `conf.d` is scanned after `php.ini`. JIT is inert beside xdebug anyway and a CLI process is too short-lived for the opcode cache, so it is off for the CLI only. ### 4. The CLI never loaded `php.ini` Ondrej looks for it at `/etc/php/<version>/cli/`, and only FPM was covered, by the explicit `php-fpm -c /etc/php/` in the service script. So composer and every `docker run <img> php ...` quietly used upstream defaults instead of the tuned config. Now linked for both SAPIs: `memory_limit` reads `128M` from `php.ini`, `expose_php` is `Off`. ### 5. nginx had never started The overlay's `nginx.conf` includes `/etc/nginx/mime.types`, which only the distro package provides, but `INSTALL_PHP` removed `/etc/nginx` wholesale. Alpine removes only `/etc/php*`, which is why it never showed there. nginx crash-looped: ``` open() "/etc/nginx/mime.types" failed (2: No such file or directory) in /etc/nginx/nginx.conf:18 ``` Only Ubuntu's own vhost wiring is removed now. The 7.4 healthcheck block also carried a mis-indented `configs:` that would not have parsed. --- ### Interaction with `main` Merged `origin/main`, which lands pcov (#37) on these images. The two changes reinforce each other rather than collide: - pcov **is** packaged for Ubuntu, so `pcov.so` is on disk and the prune correctly **keeps** `51_pcov.ini`. pcov loads with `pcov.enabled='0'`, and `php.sh` reports *"pcov present and correctly disabled by default: OK"*. - main's new check reads `$(php -r 'echo ini_get("pcov.enabled") ? "on" : "";')` and fails if non-empty. On Ubuntu 8.x that would have captured the JIT warning and **falsely** reported "pcov is enabled by default" — fix 3 is what makes it pass. - main's `51_pcov.ini` documents that correct coverage requires `opcache.enable_cli=0`, calling it a correctness requirement that fails silently. Fix 3 makes that the Ubuntu default. ### Verification All five assertions **and** all five healthchecks pass, and are wired into the aggregator. The healthchecks were checked beyond the health flag: HTTP 200, 98KB phpinfo, PHP 8.4.24, zero nginx errors. `fs/php-nginx/etc/validate.d/php.sh` is shared, so the other families were re-verified: `php-85`, `php-83`, `php-74`, `magento-php-85`, `php-85-node`, `frankenphp-85` all pass. `frankenphp` carries its own copy and is untouched. ### Still out of scope - `fs/php-frankenphp/etc/validate.d/php.sh` keeps the same fragile `head -n 1`. It passes today, so the duplication is left rather than changing a file with no failing case. - `tea` cannot operate on this repo at all — its git library rejects it with `core.repositoryformatversion does not support extension: worktreeconfig`, from both a worktree and the main checkout. This PR and its comments were made through the Forgejo API. CLAUDE.md directs PR work through `tea`, so that instruction will fail for anyone with the same config. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(ubuntu-php): make the Ubuntu PHP images pass validate, and gate them
Some checks failed
Build / Run container tests (push) Failing after 33m26s
Build / Build (push) Has been skipped
182252ac49
The ubuntu-php assertions have been commented out in test.yml because the
images could not pass their build-time validate. Three separate faults were
in the way.

NGINX_VERSION was declared 1.28 on every Ubuntu stage, but all of them build
FROM ubuntu-24-base and noble ships nginx 1.24 (the ondrej PPA does not carry
nginx, so nothing bumps it). The ARG is descriptive, not prescriptive -- it
feeds the ooo.grey.version.nginx label and the validate assertion and selects
nothing -- and PHP.Dockerfile already varies it per base, 1.28/1.24/1.20, to
match what each Alpine actually ships. Alpine running 1.28 is what its repo
happens to ship rather than a target we pursue, so record 1.24 here instead of
adding nginx.org's repo and making Ubuntu the only image bypassing its distro.

Extensions never loaded on 8.x. The shared fs/php-nginx overlay uses Alpine's
flat /etc/php, which works there because `ln -s /etc/php /etc/php${PHP_VER}`
covers the only path PHP reads. Ondrej compiles in /etc/php/<version>/{cli,fpm}
instead, which sits inside /etc/php where that symlink cannot reach, so conf.d
was never scanned. FIX_PERMS reshaped the tree into the versioned layout only
under `if [[ "$PHP_VER" -eq 7 ]]`, leaving every 8.x image with just its
built-ins -- php -m listed 18 modules while 51 .so files sat unused. Link the
versioned paths back at the flat ones for all versions, as symlinks rather than
the copies the 7.4 branch used, so the runtime toggles in services.d/php/run
still reach the files PHP reads. That branch is now only the pm.max_spawn_rate
fixup it was documented to be. ubuntu-php-84 goes 18 -> 65 modules.

Once conf.d was scanned, PHP warned about every extension in it that ondrej
builds in or omits, on every invocation, so prune the ini files that can never
load. The last of those warnings, opcache disabling JIT because xdebug overrides
zend_execute_ex, is legitimate and stays; it broke validate only because php.sh
read `php --version | head -n 1` and PHP prints startup warnings to stdout, so
select the version line explicitly.

All five ubuntu-php assertions now pass and are wired into the test aggregator.
Verified no regression in the php, magento, php-node and frankenphp images,
which share validate.d/php.sh (frankenphp carries its own copy, untouched).

Co-Authored-By: Claude <noreply@anthropic.com>
fix(ubuntu-php): stop the json ini cleanup reporting a miss
All checks were successful
Build / Run container tests (push) Successful in 23m18s
Build / Build (push) Successful in 3m35s
ab148fb5e2
The extension prune added in the previous commit already drops 00_json.ini,
since ondrej builds json into the binary and leaves no json.so behind, so the
later json-specific removal always missed and printed

  rm: cannot remove '/etc/php/conf.d/*_json.ini': No such file or directory

into every 8.x build log. `|| true` swallowed the exit code but not the
message; -f swallows both.

Co-Authored-By: Claude <noreply@anthropic.com>
Author
Owner

CI: run 294 failed, but not on this change

Run 294 is red. The build and validation phases were entirely clean — 41 × All validations passed, 0 × Validation failed across the whole matrix, with 8 nginx checks landing on 1.24. All five docker-ubuntu-php-*-assertions-1 containers reached Created.

It broke ~19 minutes in, during compose up container recreation:

Container docker-java-21-tomcat-assertions-1 Error response from daemon:
removal of container ffbc7e8b... is already in progress

A container-removal race on the shared Swarm daemon, on a Java Tomcat service that this diff does not touch. There were ~5 runs executing concurrently at the time — the contention mode CLAUDE.md warns about, where the failure says nothing about the change under test.

Re-pushed as ab148fb with two runs in flight instead of five; run 303 is monitoring.

One real thing the log did catch

The 294 log showed this in every 8.x build:

rm: cannot remove '/etc/php/conf.d/*_json.ini': No such file or directory

Self-inflicted by this PR. The new extension prune already drops 00_json.ini — ondrej builds json into the binary and leaves no json.so — so the later json-specific removal always missed. || true swallowed the exit code but not the message. Now rm -f, which swallows both. Fixed in ab148fb.

### CI: run 294 failed, but not on this change [Run 294](https://git.grey.ooo/Grey.ooo/docker/actions/runs/294) is red. The build and validation phases were entirely clean — **41 × `All validations passed`, 0 × `Validation failed`** across the whole matrix, with 8 nginx checks landing on `1.24`. All five `docker-ubuntu-php-*-assertions-1` containers reached `Created`. It broke ~19 minutes in, during `compose up` container recreation: ``` Container docker-java-21-tomcat-assertions-1 Error response from daemon: removal of container ffbc7e8b... is already in progress ``` A container-removal race on the shared Swarm daemon, on a Java Tomcat service that this diff does not touch. There were ~5 runs executing concurrently at the time — the contention mode CLAUDE.md warns about, where the failure says nothing about the change under test. Re-pushed as `ab148fb` with two runs in flight instead of five; [run 303](https://git.grey.ooo/Grey.ooo/docker/actions/runs/303) is monitoring. ### One real thing the log did catch The 294 log showed this in every 8.x build: ``` rm: cannot remove '/etc/php/conf.d/*_json.ini': No such file or directory ``` Self-inflicted by this PR. The new extension prune already drops `00_json.ini` — ondrej builds json into the binary and leaves no `json.so` — so the later json-specific removal always missed. `|| true` swallowed the exit code but not the message. Now `rm -f`, which swallows both. Fixed in `ab148fb`.
Author
Owner

CI green

Run 303 succeeded — both Build and Run container tests.

  • Validation failed: 0
  • nginx checks landing on 1.24: 5 (one per Ubuntu stage)
  • All five docker-ubuntu-php-*-assertions-1 containers CreatedStarted → completed successfully, so the newly uncommented gate in test.yml is genuinely being enforced rather than skipped
  • The rm: cannot remove '*_json.ini' noise is gone

This run was scoped rather than full-matrix: ab148fb only touches PHP.Ubuntu-fragment.Dockerfile, so changed-targets correctly narrowed it to the ubuntu-php images. The full-matrix coverage came from run 294, whose build and validation phases were clean end to end and which failed only on the shared-daemon container-removal race described above.

### CI green [Run 303](https://git.grey.ooo/Grey.ooo/docker/actions/runs/303) succeeded — both `Build` and `Run container tests`. - `Validation failed`: **0** - nginx checks landing on `1.24`: **5** (one per Ubuntu stage) - All five `docker-ubuntu-php-*-assertions-1` containers `Created` → `Started` → completed successfully, so the newly uncommented gate in `test.yml` is genuinely being enforced rather than skipped - The `rm: cannot remove '*_json.ini'` noise is gone This run was scoped rather than full-matrix: `ab148fb` only touches `PHP.Ubuntu-fragment.Dockerfile`, so `changed-targets` correctly narrowed it to the `ubuntu-php` images. The full-matrix coverage came from run 294, whose build and validation phases were clean end to end and which failed only on the shared-daemon container-removal race described above.
fix(ubuntu-php): let the CLI see php.ini, and get the images actually serving
Some checks failed
Build / Build (push) Has been cancelled
Build / Run container tests (push) Has been cancelled
4f9fd6be0c
Two follow-ups from the previous commits, both of which needed the images to be
run rather than merely built.

The CLI never loaded php.ini. Ondrej looks for it at /etc/php/<version>/cli/
while the overlay keeps it flat, and only FPM was covered, by the explicit
`php-fpm -c /etc/php/` in services.d/php/run. So composer and every
`docker run <img> php ...` quietly used upstream defaults instead of the tuned
config. Linking it was tried in the first pass and backed out because it broke
validate, but that turned out to be the fragile `head -n 1` version parse,
which is now fixed, so link it for both SAPIs. memory_limit reads 128M from
php.ini instead of PHP's built-in 128M-by-accident, and expose_php is Off.

That link also made a pre-existing wart unmissable rather than causing it:
ondrej's opcache has a real JIT where Alpine's does not, and the xdebug we ship
overrides zend_execute_ex, so every CLI startup printed "JIT disabled" to
stdout, corrupting the output of any script being piped. Of the settings that
suppress it, only opcache.enable_cli is CLI-scoped -- opcache.jit and
jit_buffer_size live in the shared conf.d and would cost FPM its JIT, and
display_errors there would override the PHP_DISPLAY_ERRORS tunable, since
conf.d is scanned after php.ini. JIT is inert next to xdebug anyway and a CLI
process is too short-lived for the opcode cache, so turn it off for the CLI.

nginx had never started in these images. The overlay's nginx.conf includes
/etc/nginx/mime.types, which only the distro package provides, but INSTALL_PHP
removed /etc/nginx wholesale -- Alpine only removes /etc/php*, which is why it
never showed there. nginx crash-looped on

  open() "/etc/nginx/mime.types" failed (2: No such file or directory)

so only Ubuntu's own vhost wiring is removed now. This is what the commented-out
healthchecks were hiding: the images passed build-time validate while being
unable to serve a request. All five ubuntu-php healthchecks are re-enabled and
wired into the aggregator, serving phpinfo over HTTP 200 with no nginx errors.
The 7.4 block also had a mis-indented `configs:` that would not have parsed.

Co-Authored-By: Claude <noreply@anthropic.com>
Merge remote-tracking branch 'origin/main' into claude/nervous-sinoussi-ff5f90
All checks were successful
Build / Run container tests (push) Successful in 27m19s
Build / Build (push) Successful in 35m28s
0fc7af3855
geusebio changed title from fix(ubuntu-php): make the Ubuntu PHP images pass validate, and gate them to fix(ubuntu-php): get the Ubuntu PHP images working, and gate them 2026-08-08 02:13:07 +00:00
Author
Owner

Rebased onto current main, and the pcov work lines up

main had moved on a fair way, including two changes that touch this PR directly. Merged it in (0fc7af3) — no conflicts, and both sides survived: NGINX_VERSION=1.24 alongside the new php<ver>-pcov packages, and the robust version parse alongside the new pcov assertion block.

The pcov work (#37) and this PR reinforce each other:

  • pcov is packaged for Ubuntu, so pcov.so lands on disk and the extension prune here correctly keeps 51_pcov.ini. Verified on a fresh 8.5 build: pcov loaded, pcov.enabled='0', and php.sh reporting "pcov present and correctly disabled by default: OK".
  • main's new check reads $(php -r 'echo ini_get("pcov.enabled") ? "on" : "";') and fails when that is non-empty. On Ubuntu 8.x it would have captured the JIT disabled warning on stdout and falsely failed with "pcov is enabled by default". The opcache.enable_cli fix in this PR is what keeps that probe clean.
  • 51_pcov.ini calls opcache.enable_cli=0 a correctness requirement for coverage that otherwise fails silently. This PR makes it the Ubuntu default.

One thing worth knowing for anyone verifying locally: #43 changed the compose project name, so built images are now docker-<runid>-* rather than <dir>-*. I inspected the old names at first and got a stale answer — pcov looked absent when it was in fact installed.

All ten Ubuntu services (5 assertions + 5 healthchecks) pass against merged main.

Run 308 shows cancelled, not failed: pushing the merge to the same branch superseded it. Run 312 covers the merge and is being monitored.

### Rebased onto current `main`, and the pcov work lines up `main` had moved on a fair way, including two changes that touch this PR directly. Merged it in (`0fc7af3`) — no conflicts, and both sides survived: `NGINX_VERSION=1.24` alongside the new `php<ver>-pcov` packages, and the robust version parse alongside the new pcov assertion block. The pcov work (#37) and this PR reinforce each other: - pcov **is** packaged for Ubuntu, so `pcov.so` lands on disk and the extension prune here correctly **keeps** `51_pcov.ini`. Verified on a fresh 8.5 build: pcov loaded, `pcov.enabled='0'`, and `php.sh` reporting *"pcov present and correctly disabled by default: OK"*. - main's new check reads `$(php -r 'echo ini_get("pcov.enabled") ? "on" : "";')` and fails when that is non-empty. On Ubuntu 8.x it would have captured the `JIT disabled` warning on stdout and **falsely** failed with "pcov is enabled by default". The `opcache.enable_cli` fix in this PR is what keeps that probe clean. - `51_pcov.ini` calls `opcache.enable_cli=0` a correctness requirement for coverage that otherwise fails silently. This PR makes it the Ubuntu default. One thing worth knowing for anyone verifying locally: #43 changed the compose project name, so built images are now `docker-<runid>-*` rather than `<dir>-*`. I inspected the old names at first and got a stale answer — pcov looked absent when it was in fact installed. All ten Ubuntu services (5 assertions + 5 healthchecks) pass against merged `main`. Run 308 shows cancelled, not failed: pushing the merge to the same branch superseded it. [Run 312](https://git.grey.ooo/Grey.ooo/docker/actions/runs/312) covers the merge and is being monitored.
fix(ubuntu-php): take nginx from nginx.org again, and bake the images in CI
Some checks failed
Build / Run container tests (push) Failing after 1m57s
Build / Build (push) Has been skipped
68171a931a
Consolidates PR #7, which reached the same diagnosis independently back in
July and carried two things this branch did not.

The nginx version was the more important of them. This branch had recorded
NGINX_VERSION=1.24 to match what noble ships, on the reasoning that the ARG is
descriptive and Alpine's 1.28 was incidental. PR #7 supplies the history that
makes that wrong: these images deliberately ran a current nginx from
ppa:ondrej/nginx, that PPA was dropped in the FrankenPHP commit, and it has
since been deleted from Launchpad entirely -- confirmed, it now 404s while
ppa:ondrej/php is still up. So 1.28 recorded a real intent and the slide to
1.24 was a regression, not a stale constant. Take the current stable from
nginx.org, as #7 proposed: nginx 1.30.4, so the recorded version is one the
image actually runs.

Note the tripwire that comes with it. NGINX_VERSION pins major.minor against a
rolling repository, so validate will fail the day nginx.org moves to 1.32.
That is the same deal the Alpine images already take against their own repo,
and a loud failure is the point -- it is what caught this regression.

#7 also wanted ubuntu-php built in CI. Its mechanism is gone: main replaced the
per-target matrix with ./changed-targets scoping, and raised the timeout past
the 45 minutes it asked for. The equivalent now is putting the targets in the
`default` group, which is both what gets built and pushed and what
changed-targets scopes off -- so a change to PHP.Ubuntu.Dockerfile currently
bakes nothing whatsoever. They were held out of `default` while they could not
pass validation; that no longer applies. This starts publishing
matthewbaggett/php-ubuntu:* from main.

What #7 did not have, and what this branch keeps: nginx never actually started,
because /etc/nginx was removed wholesale and with it the mime.types the
overlay's nginx.conf includes -- #7 would still have shipped a dead web server,
since it kept that rm and never enabled the healthchecks that expose it. The
same fix applies unchanged to nginx.org's packaging, whose default vhost lands
in conf.d rather than sites-enabled. Also kept: opcache off for the CLI, without
which the JIT warning on stdout would false-fail main's new pcov probe.

Verified with nginx from nginx.org: all five assertions and all five
healthchecks pass, nginx -v reports 1.30.4 with no "(Ubuntu)" suffix, mime.types
survives, and the images serve phpinfo over HTTP 200 with no nginx errors.

Co-Authored-By: Claude <noreply@anthropic.com>
geusebio force-pushed claude/nervous-sinoussi-ff5f90 from 68171a931a
Some checks failed
Build / Run container tests (push) Failing after 1m57s
Build / Build (push) Has been skipped
to f07086cd48
Some checks failed
Build / Run container tests (push) Failing after 13m29s
Build / Build (push) Has been skipped
2026-08-08 14:05:43 +00:00
Compare
Some checks failed
Build / Run container tests (push) Failing after 13m29s
Build / Build (push) Has been skipped
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin claude/nervous-sinoussi-ff5f90:claude/nervous-sinoussi-ff5f90
git switch claude/nervous-sinoussi-ff5f90

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff claude/nervous-sinoussi-ff5f90
git switch claude/nervous-sinoussi-ff5f90
git rebase main
git switch main
git merge --ff-only claude/nervous-sinoussi-ff5f90
git switch claude/nervous-sinoussi-ff5f90
git rebase main
git switch main
git merge --no-ff claude/nervous-sinoussi-ff5f90
git switch main
git merge --squash claude/nervous-sinoussi-ff5f90
git switch main
git merge --ff-only claude/nervous-sinoussi-ff5f90
git switch main
git merge claude/nervous-sinoussi-ff5f90
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Grey.ooo/docker!41
No description provided.