Repository navigation
perf: de-bloat FPM images by dropping build-only packages - #26
Merged
Merged
Conversation
Build the PHP extensions in a single layer that installs the -dev packages, compiles, and purges them again, keeping only the runtime libraries the extensions link against (the official php image's apt-mark/ldd technique). Previously headers, static libraries and the extracted PHP source (~145 MB, left behind by a separate gd configure layer) shipped in every image. Install runtime packages with --no-install-recommends, naming the recommends that do real work (openssh-client and less for git, ImageMagick's extra coders and HEIC/AVIF encoders, Ghostscript's CJK fallback font, the perl modules mariadb-client's tools need). This drops exim4, dbus, systemd extras, netpbm and docs. Drop `docker-php-ext-install xml`: xml is compiled into the official image, so it only produced an xml.so that was never loaded. The build now fails if PHP prints a startup warning or an expected extension does not load.
The FPM workflow only builds on master and pushes straight to the published tags, so a broken Dockerfile was only found after merge. Add a pull-request workflow that builds all four FPM images per version and arch without pushing, checks extensions, tools and Apache -> FPM, and reports sizes against the published tags in the job summary. Also rebuild the FPM images when bin/ changes: pecl-install and fetch-geoip-db are copied into them.
Overlapping runs (push during the scheduled rebuild, a dispatch) raced on the arch tags, and the merge jobs could build :latest from arch images of different runs. Queue runs in one concurrency group without cancelling, since a run cancelled mid-push leaves the arch tags out of step. The token is only used for checkout, so limit it to contents: read.
dpkg-query --search also prints "diversion by X from/to: <path>" lines.
They reached apt-mark as package names ("diversion", "by", ...), which
failed the build with exit 123 on every arch and version. Drop them, and
split "pkg-a:arch, pkg-b: <path>" lines so every owning package is kept.
Debian's apache2 package installs /var/www/html/index.html, which DirectoryIndex serves for /, so the check never reached PHP-FPM.
Job summaries are only visible in the web UI, not through the API or gh run view --log.
imorland
force-pushed
the
im/fpm-debloat
branch
from
October 31, 2026 17:13
5ddc763 to
28f29ff
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Removes build-time leftovers from the
php83fpm/php85fpmimages. All tools, extensions, ImageMagick/Ghostscript, AWS CLI and the GeoIP databases stay.Changes
-devpackages, compiles, and purges them, keeping only the runtime libraries the extensions link against. This is the official php image'sapt-mark+lddtechnique.gdconfigure step (145 MB on disk) no longer ships.--no-install-recommends. Recommends that do real work are named explicitly:openssh-client/lessfor git, ImageMagick's extra coders and HEIC/AVIF encoders, Ghostscript's CJK fallback font, and the perl modules formytop/innotop. Dropped: exim4, dbus, systemd extras, netpbm, docs.docker-php-ext-install xmlis removed.xmlis compiled into the official image, so this step only produced anxml.sothat was never loaded.docker-image-fpm-check.ymlbuilds all FPM images on pull requests without pushing. It smoke-tests extensions, tools and Apache → FPM, and writes sizes against the published tags to the job summary.bin/changes, sincepecl-installandfetch-geoip-dbare copied into these images.Measured size (uncompressed, local image store, from the check workflow; published tags vs this PR):
latestclidevcli-devAbout 355–366 MB (≈21%) smaller per tag. The compressed pull size was estimated from the published layers at roughly 548 → 460 MB for
php85fpm:latest; it wasn't measured, because nothing is pushed.Behaviour changes
-devpackage themselves. This is documented in each README.mail()now fails instead of queueing to a container-local mailbox that was never delivered anywhere.