Skip to content

Ship the application as two production Docker images - #95

Merged
lyrixx merged 2 commits into
mainfrom
prod-images
Sep 25, 2026
Merged

lyrixx merged 2 commits into
mainfrom
prod-images

Conversation

@lyrixx

@lyrixx lyrixx commented Sep 25, 2026

Copy link
Copy Markdown
Member

Same as jolicode/qotd#106: the application now ships as two self-contained Docker images. The CI builds them and pushes them to GHCR on every push to main and on every tag:

  • php: php-fpm listening on the unix socket /var/run/php/php-fpm.sock, with the code and the vendors baked in, APP_ENV=prod. The same image is used for CLI commands (bin/console), e.g. the migrations.
  • nginx: the official nginx image with the public/ directory and the site configuration, forwarding PHP requests to that socket.

Both run as non-root users. Everything else (secrets, database, Slack credentials, dashboard password) is provided through environment variables at runtime.

Other changes:

  • the dev frontend container and the production images now share the same php-fpm and nginx configuration (services/php/php/, services/php/nginx/); the production-only settings are in services/php/php/mods-available/app-prod.ini. The dev php-fpm listens on the same unix socket, and the dev container listens on port 8080;
  • the prod castor context now runs the usual tasks on a dedicated compose stack, to test the images locally: castor build -c prod, castor start -c prod, castor destroy -c prod (see the README). It replaces the previous prod context, which pointed to the real domain;
  • castor docker:push --tag=... now pushes the images too, not just the build cache. The new "Build and push production images" workflow uses it. Images are tagged with the short commit sha, latest on main, and the git tag when there is one.

Differences with qotd: no asset-mapper, uploads volume or cron (monologue doesn't use them). --tag is simpler because docker:push now runs buildx bake directly on the compose files (#93). I also added hadolint ignores for COPY --from=app, because app is a build context and not a stage.

* "php" (php-fpm on a unix socket, code and vendors baked in, APP_ENV=prod,
  also the CLI image) and "nginx" images, built from the new production
  stages of the Dockerfile, running as non-root users
* php-fpm and nginx configuration shared between the dev frontend container
  and the production images
* "prod" castor context to build, run and push the images on a dedicated
  compose stack
* castor docker:push --tag also pushes the images
* "Build and push production images" workflow, on every push to main and
  every tag
Symfony calls the autocomplete callback with a CompletionInput, which
get_service_names() received as the profile name: no service matched,
so nothing was ever suggested.
@lyrixx
lyrixx merged commit 656e659 into main Sep 25, 2026
2 checks passed
@lyrixx
lyrixx deleted the prod-images branch September 25, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant