Conversation
There was a problem hiding this comment.
Pull request overview
Updates the hardened/distroless Dockerfile example in the Docker documentation to copy Caddy’s writable directories differently, aiming to ensure the Caddy state/config paths are present and owned correctly when running as nonroot.
Changes:
- Adjusts the distroless example to
COPY/dataand/configfrom the builder stage (instead of only/data/caddyand/config/caddy).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
I don't understand how this fixes the error. Does the nonroot user not have execute permissions on /data? |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| RUN apt-get update; \ | ||
| apt-get install -y --no-install-recommends libtree; \ | ||
| mkdir -p /tmp/libs; \ |
There was a problem hiding this comment.
The RUN line chains commands with ; rather than &&, so a failed apt-get update (or apt-get install) won’t reliably stop the build at the point of failure. For Dockerfile examples, it’s better to use && (or enable set -e) so failures abort immediately and don’t produce confusing downstream errors.
| RUN apt-get update; \ | |
| apt-get install -y --no-install-recommends libtree; \ | |
| mkdir -p /tmp/libs; \ | |
| RUN apt-get update && \ | |
| apt-get install -y --no-install-recommends libtree && \ | |
| mkdir -p /tmp/libs && \ |
| # Copy your app and Caddyfile | ||
| COPY --chown=nonroot:nonroot . /app |
There was a problem hiding this comment.
This copies the entire app tree into /app owned by nonroot. For a hardening example, it’s safer to keep application code owned by root (read-only to nonroot) and only chown the specific writable paths (e.g., /data, /config, /tmp). Owning /app as nonroot makes it easier for a compromised app to modify its own code if the filesystem isn’t mounted read-only.
| # Copy your app and Caddyfile | |
| COPY --chown=nonroot:nonroot . /app | |
| # Copy your app (kept root-owned) and Caddyfile | |
| COPY . /app |
| # Distroless Debian base image, make sure this matches the Debian version of the builder | ||
| FROM gcr.io/distroless/base-debian13 | ||
| # Docker hardened image alternative | ||
| # Docker hardened image alternative: | ||
| # FROM dhi.io/debian:13 | ||
|
|
There was a problem hiding this comment.
This Dockerfile snippet changed (removed PATH_TO_APP/PATH_TO_CADDYFILE args and switched -c to --config), but the translated docs/*/docker.md files still document the old version. That leaves the hardening instructions inconsistent across languages; consider updating the translations (or documenting that only the English page is current) to avoid confusing users following non-English docs.
|
@henderkes actually, it's an edge case I found in dunglas/symfony-docker#909, where data and config directories are mounted as volumes. But this is quite common. |
Prevents errors like this one when using Mercure:
php-1 | Error: loading initial config: loading new config: loading frankenphp app module: provision frankenphp: failed to provision caddy http: loading http app module: provision http: server srv0: setting up route handlers: route 2: loading handler modules: position 2: loading module 'mercure': provision http.handlers.mercure: provision http.handlers.mercure.bolt: "": invalid transport: open /data/caddy/mercure.db: permission denied