build(docker): warm prod cache at build time and add prod compose file

- Run cache:warmup in the build stage so containers start with a
  pre-built Symfony kernel and DI container
- Scope the cache volume to var/cache/prod/pools where Symfony writes
  pool data, preserving the warmed kernel across container restarts
- Add docker-compose.prod.yml for deploying the registry image without
  the dev override being picked up automatically
- Expand .dockerignore to exclude vendor/, tests/, docs, compose files,
  and env files from the build context

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-30 15:15:51 +02:00
parent 2f66c65b30
commit 50256c97ef
4 changed files with 67 additions and 5 deletions
+29 -1
View File
@@ -1,6 +1,34 @@
# Version control
.git .git
.gitea .gitea
# AI / IDE tooling
.claude
# Dev tooling
.gitignore
/.phpunit.cache
phpunit.xml.dist
tests/
# Documentation
CHANGELOG.md
CLAUDE.md
README.md
# Compose / deployment descriptors (not app code)
docker-compose.yml
docker-compose.override.yml
docker-compose.prod.yml
# Dependencies — re-installed from lockfile in the build stage;
# a local vendor/ in the build context would silently override the clean install
vendor/
# Runtime dirs (generated at build or run time, not from source)
var/ var/
# Env files — config is injected at runtime via Docker environment variables
.env
.env.local .env.local
.env.*.local .env.*.local
docker-compose.override.yml
+5 -3
View File
@@ -21,7 +21,9 @@ RUN composer install \
# ── build stage (generate optimised classmap with source present) ────────────── # ── build stage (generate optimised classmap with source present) ──────────────
FROM deps AS build FROM deps AS build
COPY . . COPY . .
RUN composer dump-autoload --optimize --no-dev --no-interaction RUN composer dump-autoload --optimize --no-dev --no-interaction && \
mkdir -p var/cache var/log && \
APP_ENV=prod APP_SECRET=placeholder php bin/console cache:warmup --no-debug
# ── dev stage (all deps + Xdebug, source is mounted at runtime) ─────────────── # ── dev stage (all deps + Xdebug, source is mounted at runtime) ───────────────
FROM base AS dev FROM base AS dev
@@ -44,11 +46,11 @@ FROM base AS final
RUN addgroup -S app && adduser -S -G app app RUN addgroup -S app && adduser -S -G app app
COPY --from=build /app/vendor /app/vendor COPY --from=build /app/vendor /app/vendor
COPY --from=build /app/var/cache/prod /app/var/cache/prod
COPY . . COPY . .
COPY docker/frankenphp/Caddyfile /etc/caddy/Caddyfile COPY docker/frankenphp/Caddyfile /etc/caddy/Caddyfile
RUN mkdir -p var/cache var/log \ RUN mkdir -p var/cache/prod/pools var/log && chown -R app:app /app
&& chown -R app:app /app
USER app USER app
+32
View File
@@ -0,0 +1,32 @@
services:
graph:
image: git.arthurerlich.de/haylan/git-contribution-graph:latest
container_name: git-contribution-graph
restart: unless-stopped
ports:
- "8080:8080"
environment:
APP_ENV: prod
APP_DEBUG: "0"
APP_SECRET: "${APP_SECRET}"
ALLOWED_HOSTS: "${ALLOWED_HOSTS:-}"
GITHUB_USER: "${GITHUB_USER:-}"
GITHUB_TOKEN: "${GITHUB_TOKEN:-}"
GITLAB_USER: "${GITLAB_USER:-}"
GITLAB_TOKEN: "${GITLAB_TOKEN:-}"
GITLAB_URL: "${GITLAB_URL:-}"
GITEA_USER: "${GITEA_USER:-}"
GITEA_TOKEN: "${GITEA_TOKEN:-}"
GITEA_URL: "${GITEA_URL:-}"
volumes:
- cache:/app/var/cache/prod/pools
- logs:/app/var/log
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
volumes:
cache:
logs:
+1 -1
View File
@@ -21,7 +21,7 @@ services:
GITEA_TOKEN: "${GITEA_TOKEN:-}" GITEA_TOKEN: "${GITEA_TOKEN:-}"
GITEA_URL: "${GITEA_URL:-}" GITEA_URL: "${GITEA_URL:-}"
volumes: volumes:
- cache:/app/var/cache - cache:/app/var/cache/prod/pools
- logs:/app/var/log - logs:/app/var/log
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"] test: ["CMD", "curl", "-f", "http://localhost:8080/health"]