Conversation
* "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. Build steps (composer, yarn/npm, AssetMapper, cache warmup) only run when the application needs them * php-fpm and nginx configuration shared between the dev frontend container and the production images (the frontend now listens on port 8080) * "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, commented in docker-starter and enabled by castor init * CI job testing the production images
The username was a bare "$": GHCR accepts any username with a GITHUB_TOKEN, so it worked by accident.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Same approach as in jolicode/monologue: the application can now ship as two self-contained, production-ready images.
What's inside
phpimage: php-fpm on the unix socket/var/run/php/php-fpm.sock, code and vendors baked in,APP_ENV=prod, non-root user (uid 1000). It is also the CLI image (migrations, crons, workers).nginximage: officialnginx:1.28-alpine, thepublic/directory and the site configuration.infrastructure/docker/services/php/Dockerfile, withapplication/as theappbuild context (application/.dockerignore). Each build step (composer install+dump-env, yarn/npm build, AssetMapper compile, cache warmup) only runs if the application needs it, so the bare starter builds too.services/php/php/andservices/php/nginx/, used by both the devfrontendcontainer and the production images. Production-only PHP settings are inapp-prod.ini.prodcastor context: dedicated compose stack (docker-compose.prod.yml: postgres + the two images, no bind mounts, no router) on http://127.0.0.1:8000, e.g.castor start -c prod,castor builder -c prod,castor destroy -c prod.castor docker:push --tag=...also pushes the images, not only their build cache..github/workflows/build-push.yml: pushes the images to GHCR onmainand on tags. Commented out in docker-starter (nothing to deploy),castor inituncomments it.prod-imagesjob that starts the production stack and checks the response, removed with the rest of.github/bycastor init.Breaking changes for existing projects
frontendcontainer now listens on port 8080 (was 80), and php-fpm on a unix socket instead of127.0.0.1:9000. Traefik picks the new port automatically, unless a project hardcodesloadbalancer.server.port=80.frontend/etc/nginx/nginx.conftonginx/conf.d/default.conf(README cookbooks updated). The static-assetsno-cacheblock was dropped.Tested locally
castor start -c prodon the bare starter: stack healthy, "Environment: prod",/index.phpreturns 404,/php-fpm-statusreturns 403,var/not baked indump-env,asset-map:compileand cache warmup run; both images healthy and servingcastor docker:push -c prod --tag=... --dry-rungenerates the expected bake filecastor initoutput: onlybuild-push.ymlis kept, uncommented, and passes actionlint