Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.frankenpress.com/llms.txt

Use this file to discover all available pages before exploring further.

fp-runtime is the base container image every FrankenPress site extends. It ships:
ComponentVersionNotes
FrankenPHP1.12.2Caddy + PHP 8.3 runtime, single statically-linked binary
caddyserver/cache-handlerv0.16.0Souin HTTP cache, compiled into the FrankenPHP binary via xcaddy
darkweak/storages/go-redis/caddyv0.0.19Redis storage backend for Souin
dunglas/caddy-cbrotliv1.0.1Brotli encoding
WP-CLI2.12.0Cron + admin tasks
PHP extensionsgd, intl, exif, zip, opcache, mysqli, pdo_mysql, memcached, redisWP-friendly set
fp-mu-pluginconfigurableBaked at build time via FP_MU_PLUGIN_VERSION (default: v0.1.1)
Published image: ghcr.io/eightoeight/fp-runtime:php8.3 (pulled multi-arch eventually; currently linux/amd64).

Consumer pattern

Downstream sites build on top:
# In your-site/Dockerfile
FROM composer:2 AS deps
COPY composer.* /app/
WORKDIR /app
RUN composer install --no-dev --no-scripts --optimize-autoloader

FROM ghcr.io/eightoeight/fp-runtime:php8.3
COPY --from=deps /app/vendor /app/vendor
COPY web /app/web
COPY config /app/config
fp-site-template ships this Dockerfile out of the box.

Environment variables

All optional. Defaults produce a working config out of the box.
VarDefaultPurpose
REDIS_URLredis:6379Address of the Redis used by Souin’s HTTP cache
FP_CACHE_TTL5mDefault cache entry TTL
FP_CACHE_STALE1hStale-while-revalidate window
FP_CACHE_DEFAULT_CONTROLpublic, s-maxage=300Cache-Control fallback when upstream doesn’t set one
FP_DOCROOT/app/webWordPress webroot inside the container
FP_PORT8080Public HTTP listen port
FP_METRICS_PORT9145Prometheus metrics listen port (separate from public traffic)

Build args

Override at build time with --build-arg:
ArgDefault
PHP_VERSION8.3
FRANKENPHP_VERSION1.12.2
CACHE_HANDLER_VERSIONv0.16.0
STORAGES_GO_REDIS_VERSIONv0.0.19
CADDY_CBROTLI_VERSIONv1.0.1
WP_CLI_VERSION2.12.0
FP_MU_PLUGIN_VERSIONv0.1.1 (set to "" to skip baking)

Page cache invalidation

Souin caches GET responses in Redis. Invalidation is performed by fp-mu-plugin’s SouinInvalidator, connecting directly to Redis and DELing cache keys. Souin’s documented HTTP invalidation APIs (PURGE, POST-CRUD, /api.souin/* admin) are broken in cache-handler v0.16.0 — the workaround is empirical. Redis key shape (verified):
GET-<scheme>-<host>-<path>     cached response body
IDX_GET-<scheme>-<host>-<path> index entry pointing at the body
SURROGATE_<tag>                set of cache keys for a given Surrogate-Key tag
Bulk tag-based invalidation: read SURROGATE_<tag> (a Redis SET), then pipeline-DEL all members. Sub-millisecond. Full investigation log: fp-runtime/PHASE-0.md.

Local development

git clone https://github.com/EightOEight/fp-runtime
cd fp-runtime
make build         # build fp-runtime:dev
make up            # docker compose up -d (runtime + redis)
make test          # run tests/cache-spike.sh
make down          # tear down
make ci            # all of the above in one shot

CI / publishing

The image is built and pushed by GitHub Actions on every push to main and on v*.*.* tag pushes. Tags include a short SHA for traceability:
ghcr.io/eightoeight/fp-runtime:php8.3-<short-sha>
ghcr.io/eightoeight/fp-runtime:php8.3                # rolling on main
ghcr.io/eightoeight/fp-runtime:vX.Y.Z                # release tag
ghcr.io/eightoeight/fp-runtime:php8.3-vX.Y.Z         # release tag, php-prefixed