Skip to content

Add Docker Hardened Images pilot for the min flavor (-hardened-test) - #268

Open
berfinyuksel wants to merge 7 commits into
5.xfrom
feat/dhi-hardened-test-pilot
Open

berfinyuksel wants to merge 7 commits into
5.xfrom
feat/dhi-hardened-test-pilot

Conversation

@berfinyuksel

Copy link
Copy Markdown
Contributor

Applies the decisions from pimcore/DevOps-Tasks#84 (research on hardened base images as an alternative to Copa).

What this adds

  • Dockerfile.dhi – experimental min image built from dhi.io/php:<ver>-debian13-{dev,fpm} (Docker Hardened Images, Apache-2.0, Debian 13 only). The extensions DHI does not compile in (bcmath exif gd pcntl pdo_mysql sockets zip and PECL amqp) are built with phpize in the -dev stage and copied, together with only the shared libraries the distroless runtime lacks, into the -fpm runtime. The php CLI is taken from the DHI CLI image of the same version. The result runs as uid 65532 with no shell and no package manager; our php.ini, fpm env config and composer are included.
  • .github/workflows/hardened-test.yml – workflow_dispatch only, amd64 only. Builds the regular min image and the DHI min image, runs the same extension/composer smoke checks as test.yml (plus CLI/fpm ABI, nonroot and env-substitution checks), scans both with Trivy and writes a side-by-side table to the step summary. Pushes pimcore/pimcore:php<ver>-min-v5-hardened-test only with publish=true.
  • README – states that -hardened publishing is paused since 2026-07-31 (which is already the case: publish_hardened defaults to false in release.yml) and documents the experimental -hardened-test tag and its limits.

release.yml is unchanged.

Why min only

DHI's apt repo (dhi.io/deb/debian/main trixie) provides hardened rebuilds of the PHP build dependencies (libpng, libjpeg, libwebp, libfreetype, libzip, librabbitmq) but not ghostscript, ImageMagick, ffmpeg, poppler, LibreOffice, Chromium, exiftool or supervisor. Those would come unpatched from plain Debian, and a distroless runtime cannot install them, so the default/max/supervisord flavors gain nothing from DHI. ImageMagick alone is the largest CVE contributor in the current known-CVEs report.

Verification

  • Nothing has been built yet: this machine has no Docker. The first hardened-test.yml dispatch from this branch (with publish=false) is the real test; expect iterations on the dhi.io login (uses the existing Docker Hub secrets), the gd configure flags and the shared-library copy.
  • Known DHI issue: [bug]: PHP image unable to build freetype extension (libbrotli-dev cannot be installed) docker-hardened-images/catalog#677 / #682 (brotli version drift breaks libfreetype-dev). The Dockerfile pins libbrotli1/libbrotli-dev to one version as a workaround.
  • test.yml is unaffected (it does not build Dockerfile.dhi); actionlint runs on this PR.

🤖 Generated with Claude Code

Applies the decisions from pimcore/DevOps-Tasks#84:

- Dockerfile.dhi: experimental `min` image built from dhi.io/php
  (Debian 13). Extensions missing in DHI (bcmath exif gd pcntl pdo_mysql
  sockets zip, amqp) are built with phpize in the -dev stage and copied,
  together with the shared libraries the distroless runtime lacks, into
  the -fpm runtime. The php CLI comes from the DHI CLI image. Runs as
  uid 65532, no shell, no package manager.
- hardened-test.yml: manual-only workflow that builds the regular and
  the DHI min image (amd64), runs the same extension/composer smoke
  checks as test.yml, scans both with Trivy and writes a comparison to
  the step summary. Pushes php<ver>-min-v5-hardened-test only with
  publish=true.
- README: state that -hardened publishing is paused since 2026-07-31
  and document the experimental -hardened-test tag and its limits
  (min only: DHI has no ghostscript, ImageMagick, ffmpeg, poppler,
  LibreOffice or Chromium).

release.yml is unchanged.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 28, 2026 15:51
… pilot

workflow_dispatch is only registered once the file is on the default
branch, so the pilot could not be exercised from the PR. Run the
build + smoke checks + Trivy comparison on pull_request (paths-filtered);
publishing stays limited to a manual dispatch with publish=true.

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The Brotli pin requests an unavailable development package, Composer cannot execute because its shebang launcher is missing, and copied libraries lack package metadata, causing vulnerability scans to undercount CVEs.

3 open issues
What changed in this PR

Adds an experimental Docker Hardened Images pilot for Pimcore’s min flavor, separate from the existing release workflow, to compare vulnerability counts with the regular image.

Changes:

  • Adds a nonroot, distroless PHP image with the required extensions, CLI, configuration and Composer.
  • Adds a manual amd64 workflow for builds, smoke checks, Trivy comparisons and optional -hardened-test publishing.
  • Documents paused -hardened publishing and the pilot’s unsupported status and limitations.
File Description
README.md Documents hardened publishing status and experimental image usage.
Dockerfile.dhi Defines the multi-stage DHI-based min image.
.github/​workflows/​hardened-test.yml Builds, checks, compares and optionally publishes the pilot image.

Review effort: Balanced

Comment thread Dockerfile.dhi Resolved
Comment thread Dockerfile.dhi Resolved
Comment thread Dockerfile.dhi Resolved
Copilot AI balanced review requested due to automatic review settings October 28, 2026 16:00
berfinyuksel and others added 2 commits October 28, 2026 17:00
ext/zip failed with 'pcre2.h: No such file or directory': PHP on DHI is
built with --with-external-pcre and the -dev image has no pcre2 headers.
zlib1g-dev is added for the same reason ahead of the gd build.

Co-Authored-By: Claude <noreply@anthropic.com>
The distroless runtime has no env binary; composer's '#!/usr/bin/env php'
shebang therefore failed with 'no such file or directory'. The phar stub
is signed, so the shebang cannot be rewritten; copy env (libc only) from
the builder instead.

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Incorrect PHP paths block the DHI build, Composer lacks its required interpreter, and missing package metadata causes the vulnerability comparison to undercount added libraries.

4 open issues
1 resolved since last review

Review effort: Balanced

Comment thread Dockerfile.dhi Resolved
Comment thread .github/workflows/hardened-test.yml Resolved
Copilot AI balanced review requested due to automatic review settings October 28, 2026 16:09
composer create-project fails in the distroless runtime with 'Unable to
launch a new process': composer shells out (rm -rf, git, unzip) and
there is no /bin/sh. The image is a runtime image; the application has
to be built elsewhere and copied in. Check composer starts and that the
pimcore platform extension requirements are met instead.

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The inherited PHP_VERSION overrides the build argument, causing COPY to target nonexistent patch-version paths and fail the DHI image build.

4 open issues

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 28, 2026 16:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Package-version and PHP path errors break builds, while missing runtime package metadata excludes shipped dependencies from vulnerability scans and makes the CVE comparison incomplete.

4 open issues

Review effort: Balanced

Comment thread README.md Outdated
> pushed on 2026-07-31 and are not refreshed. Use the plain tags; they are the supported images and
> are rebuilt on every scheduled run with all Debian security updates available at build time.
> Hardened publishing resumes once there is a strategy that delivers it consistently
> (see [pimcore/DevOps-Tasks#84](https://github.com/pimcore/DevOps-Tasks/issues/84)).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's great to include a link in the README file that cannot be accessed 🙄

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hello @jdreesen, fair point, thanks! the link is gone now :) that slipped in because i'm working on this with Claude and hadn't reviewed everything yet, which is also why the pr is still a draft. i'll go through it before marking it ready, happy to get your review!

@berfinyuksel
berfinyuksel requested a review from brusch October 29, 2026 15:35
…k PRs, README link

- Pin brotli to the libbrotli-dev candidate (with --allow-downgrades for
  libbrotli1) instead of the runtime candidate: during the drift from
  catalog#677/#682 the newest runtime build has no matching -dev package,
  so the old pin requested a version that does not exist.
- Write the dpkg status record of every package whose files are copied
  into the runtime to /var/lib/dpkg/status.d/, so Trivy sees libzip,
  librabbitmq, libpng, libjpeg, libwebp, freetype, bz2 and coreutils (env)
  in the DHI image like it does in the baseline.
- Use PHP_PREFIX for the runtime COPY paths instead of the PHP_VERSION
  build arg (the build arg did expand correctly, this just removes the
  dependency on ARG/ENV precedence); drop the unused stage ARGs.
- Skip the pilot job for fork pull requests: they get no secrets and the
  dhi.io login would fail.
- README: drop the link to the private DevOps-Tasks issue.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 29, 2026 15:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Human assessment is needed because an AMQP build failure can be silently masked, allowing an image with an AMQP ini entry but no compiled extension.

No open issues 🎉

4 resolved since last review

Review effort: Balanced

…ow comment

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 29, 2026 15:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The new distroless image has not been built, leaving native extension compilation, shared-library dependencies, and nonroot CLI/FPM startup unverified pending a successful pilot workflow run.

No open issues 🎉

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The DHI image has not been built or run, leaving registry authentication, extension and shared-library compatibility, and nonroot CLI/FPM behavior unverified pending a successful publish=false pilot.

No open issues 🎉

Review effort: Balanced

@berfinyuksel berfinyuksel added the Skip Milestone Check Exempts this PR from the mandatory milestone requirement label Oct 29, 2026
@berfinyuksel
berfinyuksel marked this pull request as ready for review October 30, 2026 11:00
@berfinyuksel berfinyuksel assigned Copilot and unassigned Copilot Oct 30, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Skip Milestone Check Exempts this PR from the mandatory milestone requirement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants