Files
preauth/Dockerfile
T
lyra abe94c6238
Tests / test (pull_request) Successful in 1m15s
build: define the Docker build in docker-bake.hcl
The build was described in two places kept in step by hand: the Dockerfile, and
the `with:` block of each docker workflow file. This moves the parts CI actually
decides — Dockerfile target, platforms, tags, build args — into docker-bake.hcl,
so the build is version-controlled with the code and reviewable in a diff.

Tags are byte-identical to the current workflows, verified with
`buildx bake --print`:

  main push   -> digitaladapt/preauth:develop
  tag v1.2.0  -> digitaladapt/preauth:latest AND digitaladapt/preauth:1.2.0

Dockerfile: the final stage gains `AS app` so bake can target it. Naming the
last stage is a no-op for a plain `docker build` — it is still the default
target — so `docker build .` behaves exactly as before.

THREE THINGS FOUND WHILE DOING THIS
-----------------------------------

1. `buildx bake --print` does NOT read the Dockerfile, so it accepts a `target`
   naming no stage. preauth's final stage was unnamed, so `target = "app"` would
   have failed at build time in CI *after the push*, with --print reporting
   success. Fixed by naming the stage.

2. The `bake` backend in docker-publish.yaml sets no layer cache, while the
   `action` backend it replaces sets cache-from/cache-to: type=gha. Neither
   existing bake user in the portfolio sets one either, so every bake build in
   the portfolio runs cold. preauth compiles APCu from source (pecl) in both
   stages, so this would have been a real regression. The bake file now sets the
   gha cache, with the override for local builds documented.

3. `ARG MAX_REQUESTS` has been documented in the Dockerfile since the Symfony
   8.1 upgrade, but no workflow ever passed it, so CI silently built with the
   500 default. It is now an explicit named variable, overridable per build.

The workflow callers that select the bake backend are NOT in this commit:
.gitea/workflows/ is protected by a pre-receive hook and only changes via a
trusted ref. They are staged in the working tree.

Verified: Dockerfile stage/target contract holds; bake file parses and resolves
under buildx 0.37; 313 tests pass; conformance 31/34 with callers staged.
2026-09-23 21:01:53 +00:00

85 lines
2.6 KiB
Docker

# use build image, to simplify final image
FROM php:8.5-trixie AS build
# install APCu and composer
RUN pecl install apcu && \
docker-php-ext-enable apcu
COPY --from=composer /usr/bin/composer /usr/bin/composer
RUN apt-get update && \
apt-get install -y unzip git
# symfony required environment variables
ENV APP_DEBUG=0
ENV APP_ENV=prod
ENV APP_SHARE_DIR=/data/preauth
# load application into build image
RUN mkdir -p /data/preauth
RUN mkdir -p /app/bin
WORKDIR /app
COPY ./bin/console /app/bin/console
COPY ./config /app/config
COPY ./public /app/public
COPY ./src /app/src
COPY ./templates /app/templates
COPY ./composer.json /app/composer.json
COPY ./composer.lock /app/composer.lock
COPY ./symfony.lock /app/symfony.lock
# install application dependencies
RUN composer install --no-dev --optimize-autoloader
RUN composer dump-env prod --empty
# start creating final image
# Named `app` so docker-bake.hcl can target it explicitly. Naming the final
# stage changes nothing for a plain `docker build` — the last stage is still
# the default build target.
FROM dunglas/frankenphp:php8.5-trixie AS app
# install APCu and curl (needed for healthcheck)
RUN pecl install apcu && \
docker-php-ext-enable apcu
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*
# symfony required environment variables
ENV APP_DEBUG=0
ENV APP_ENV=prod
ENV APP_SHARE_DIR=/data/preauth
# worker thread lifecycle: restart each PHP thread after N requests to
# contain slow memory growth. Matches the previous default loop count of
# runtime/frankenphp-symfony (removed in the Symfony 8.1 upgrade).
# Expose as a build arg so images can bake in a different default;
# MAX_REQUESTS=0 disables restarts. Runtime override: the same env var is
# read by the Caddyfile placeholder.
ARG MAX_REQUESTS=500
ENV MAX_REQUESTS=$MAX_REQUESTS
# load application into final image
WORKDIR /app
COPY --from=build /data/preauth /data/preauth
COPY --from=build /app /app
# configure container
COPY ./Caddyfile /etc/frankenphp/Caddyfile
RUN cp $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
RUN echo 'expose_php = off' > $PHP_INI_DIR/conf.d/restrict.ini
# console needs apc to manage cache
RUN echo 'apc.enable_cli = on' > $PHP_INI_DIR/conf.d/console.ini
# app uses var folder for cache storage
VOLUME ["/config", "/data"]
# runs http on standard port
EXPOSE 80
# healthcheck
HEALTHCHECK --interval=5m \
--retries=3 \
--start-interval=1s \
--start-period=10s \
--timeout=2s \
CMD curl http://localhost || exit 1