-
-
Notifications
You must be signed in to change notification settings - Fork 44
Shrink prod Docker image via multi-stage build #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
3c22500
45852b0
8b8a4e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,7 +8,67 @@ FROM dunglas/frankenphp:1.11-php8.5 AS frankenphp_upstream | |||||||||||||||
| # https://docs.docker.com/compose/compose-file/#target | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| # Base FrankenPHP image | ||||||||||||||||
| # --------------------------------------------------------------- | ||||||||||||||||
| # Builder: install prod vendor, dump autoload, warm Symfony cache | ||||||||||||||||
| # --------------------------------------------------------------- | ||||||||||||||||
| FROM frankenphp_upstream AS php_builder | ||||||||||||||||
|
|
||||||||||||||||
| WORKDIR /app | ||||||||||||||||
|
|
||||||||||||||||
| ENV COMPOSER_ALLOW_SUPERUSER=1 \ | ||||||||||||||||
| APP_ENV=prod | ||||||||||||||||
|
|
||||||||||||||||
| # hadolint ignore=DL3008 | ||||||||||||||||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||||||||||||||||
| git \ | ||||||||||||||||
| && apt-get clean \ | ||||||||||||||||
| && rm -rf /var/lib/apt/lists/* | ||||||||||||||||
|
|
||||||||||||||||
| RUN install-php-extensions \ | ||||||||||||||||
| @composer \ | ||||||||||||||||
| intl \ | ||||||||||||||||
| pdo_mysql \ | ||||||||||||||||
| zip \ | ||||||||||||||||
| ; | ||||||||||||||||
|
|
||||||||||||||||
| # Install dependencies first so the layer is cached when only sources change | ||||||||||||||||
| COPY --link composer.* symfony.* ./ | ||||||||||||||||
| RUN --mount=type=cache,target=/tmp/composer-cache \ | ||||||||||||||||
| COMPOSER_CACHE_DIR=/tmp/composer-cache \ | ||||||||||||||||
| composer install --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress | ||||||||||||||||
|
|
||||||||||||||||
| COPY --link --exclude=frankenphp/ . ./ | ||||||||||||||||
|
||||||||||||||||
|
|
||||||||||||||||
| RUN set -eux; \ | ||||||||||||||||
| mkdir -p var/cache var/log var/share; \ | ||||||||||||||||
| composer dump-autoload --classmap-authoritative --no-dev; \ | ||||||||||||||||
| composer dump-env prod; \ | ||||||||||||||||
| chmod +x bin/console; \ | ||||||||||||||||
| sync | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| # --------------------------------------------------------------- | ||||||||||||||||
| # Builder: compile frontend assets via webpack-encore | ||||||||||||||||
| # --------------------------------------------------------------- | ||||||||||||||||
| FROM node:24-alpine AS node_builder | ||||||||||||||||
|
|
||||||||||||||||
| WORKDIR /app | ||||||||||||||||
|
|
||||||||||||||||
| # package.json references "file:vendor/symfony/ux-react/assets" | ||||||||||||||||
| COPY --from=php_builder /app/vendor ./vendor | ||||||||||||||||
|
|
||||||||||||||||
| COPY --link package.json package-lock.json webpack.config.js tsconfig.json ./ | ||||||||||||||||
| COPY --link assets ./assets | ||||||||||||||||
|
|
||||||||||||||||
| RUN --mount=type=cache,target=/root/.npm \ | ||||||||||||||||
| npm ci --no-audit --no-fund | ||||||||||||||||
|
|
||||||||||||||||
| RUN npm run build | ||||||||||||||||
|
|
||||||||||||||||
|
|
||||||||||||||||
| # --------------------------------------------------------------- | ||||||||||||||||
| # Base FrankenPHP image — minimal, shared by dev and prod | ||||||||||||||||
| # --------------------------------------------------------------- | ||||||||||||||||
| FROM frankenphp_upstream AS frankenphp_base | ||||||||||||||||
|
|
||||||||||||||||
| WORKDIR /app | ||||||||||||||||
|
|
@@ -18,33 +78,27 @@ VOLUME /app/var/ | |||||||||||||||
| # persistent / runtime deps | ||||||||||||||||
| # hadolint ignore=DL3008 | ||||||||||||||||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||||||||||||||||
| file \ | ||||||||||||||||
| cron \ | ||||||||||||||||
| supervisor \ | ||||||||||||||||
| procps \ | ||||||||||||||||
| git \ | ||||||||||||||||
| cron \ | ||||||||||||||||
| file \ | ||||||||||||||||
| procps \ | ||||||||||||||||
| supervisor \ | ||||||||||||||||
| && apt-get clean \ | ||||||||||||||||
| && rm -rf /var/lib/apt/lists/* | ||||||||||||||||
|
|
||||||||||||||||
| RUN set -eux; \ | ||||||||||||||||
| install-php-extensions \ | ||||||||||||||||
| @composer \ | ||||||||||||||||
| apcu \ | ||||||||||||||||
| intl \ | ||||||||||||||||
| pdo_mysql \ | ||||||||||||||||
| opcache \ | ||||||||||||||||
| pdo_mysql \ | ||||||||||||||||
| zip \ | ||||||||||||||||
| ; | ||||||||||||||||
|
|
||||||||||||||||
| # https://getcomposer.org/doc/03-cli.md#composer-allow-superuser | ||||||||||||||||
| ENV COMPOSER_ALLOW_SUPERUSER=1 | ||||||||||||||||
|
|
||||||||||||||||
| ENV PHP_INI_SCAN_DIR=":$PHP_INI_DIR/app.conf.d" | ||||||||||||||||
|
|
||||||||||||||||
| ###> recipes ### | ||||||||||||||||
| ###< recipes ### | ||||||||||||||||
|
|
||||||||||||||||
| RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && apt-get install -y nodejs | ||||||||||||||||
|
|
||||||||||||||||
| COPY --link frankenphp/conf.d/10-app.ini $PHP_INI_DIR/app.conf.d/ | ||||||||||||||||
| COPY --link --chmod=755 frankenphp/docker-entrypoint.sh /usr/local/bin/docker-entrypoint | ||||||||||||||||
| COPY --link frankenphp/Caddyfile /etc/frankenphp/Caddyfile | ||||||||||||||||
|
|
@@ -57,26 +111,38 @@ ENTRYPOINT ["docker-entrypoint"] | |||||||||||||||
| HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1 | ||||||||||||||||
| CMD [ "frankenphp", "run", "--config", "/etc/frankenphp/Caddyfile" ] | ||||||||||||||||
|
|
||||||||||||||||
| # Dev FrankenPHP image | ||||||||||||||||
|
|
||||||||||||||||
| # --------------------------------------------------------------- | ||||||||||||||||
| # Dev image — composer + node + git + xdebug for live development | ||||||||||||||||
| # --------------------------------------------------------------- | ||||||||||||||||
| FROM frankenphp_base AS frankenphp_dev | ||||||||||||||||
|
|
||||||||||||||||
| ENV APP_ENV=dev | ||||||||||||||||
| ENV XDEBUG_MODE=off | ||||||||||||||||
| ENV FRANKENPHP_WORKER_CONFIG=watch | ||||||||||||||||
| ENV APP_ENV=dev \ | ||||||||||||||||
| XDEBUG_MODE=off \ | ||||||||||||||||
| FRANKENPHP_WORKER_CONFIG=watch \ | ||||||||||||||||
| COMPOSER_ALLOW_SUPERUSER=1 | ||||||||||||||||
|
|
||||||||||||||||
| RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" | ||||||||||||||||
| # hadolint ignore=DL3008 | ||||||||||||||||
| RUN apt-get update \ | ||||||||||||||||
| && apt-get install -y --no-install-recommends git \ | ||||||||||||||||
| && curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \ | ||||||||||||||||
| && apt-get install -y --no-install-recommends nodejs \ | ||||||||||||||||
|
Comment on lines
+127
to
+129
|
||||||||||||||||
| && apt-get install -y --no-install-recommends git \ | |
| && curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \ | |
| && apt-get install -y --no-install-recommends nodejs \ | |
| && apt-get install -y --no-install-recommends \ | |
| git \ | |
| nodejs \ | |
| npm \ |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,12 +1,14 @@ | ||||||||||||||||||||||||||||||||||||||||||
| #!/bin/sh | ||||||||||||||||||||||||||||||||||||||||||
| set -e | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| if [ -z "$(ls -A 'vendor/' 2>/dev/null)" ]; then | ||||||||||||||||||||||||||||||||||||||||||
| if command -v composer >/dev/null 2>&1 && [ -z "$(ls -A 'vendor/' 2>/dev/null)" ]; then | ||||||||||||||||||||||||||||||||||||||||||
| composer install --prefer-dist --no-progress --no-interaction | ||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| npm install | ||||||||||||||||||||||||||||||||||||||||||
| npm run build | ||||||||||||||||||||||||||||||||||||||||||
| if command -v npm >/dev/null 2>&1; then | ||||||||||||||||||||||||||||||||||||||||||
| npm install | ||||||||||||||||||||||||||||||||||||||||||
| npm run build | ||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # Display information about the current project | ||||||||||||||||||||||||||||||||||||||||||
| # Or about an error in project initialization | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -38,7 +40,8 @@ if grep -q ^DATABASE_URL= .env; then | |||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| composer run-script --no-dev post-install-cmd | ||||||||||||||||||||||||||||||||||||||||||
| php bin/console cache:clear --no-debug | ||||||||||||||||||||||||||||||||||||||||||
| php bin/console assets:install public --no-debug | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
45
|
||||||||||||||||||||||||||||||||||||||||||
| php bin/console cache:clear --no-debug | |
| php bin/console assets:install public --no-debug | |
| NO_DEBUG_FLAG='' | |
| if [ "${APP_ENV:-}" = 'prod' ] || [ "${APP_DEBUG:-}" = '0' ] || [ "${APP_DEBUG:-}" = 'false' ]; then | |
| NO_DEBUG_FLAG='--no-debug' | |
| fi | |
| php bin/console cache:clear ${NO_DEBUG_FLAG} | |
| php bin/console assets:install public ${NO_DEBUG_FLAG} |
Copilot
AI
May 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This entrypoint clears the Symfony cache and installs bundle assets on every container start. With the new multi-stage build (pre-built vendor/assets), doing this work at runtime increases startup time and reduces the benefit of building/warming once during the image build. Consider moving these steps into the php_builder stage for frankenphp_prod, or guarding them (e.g., only when the cache/assets directories are missing or behind an env flag).
| php bin/console cache:clear --no-debug | |
| php bin/console assets:install public --no-debug | |
| RUN_SYMFONY_RUNTIME_SETUP="${RUN_SYMFONY_RUNTIME_SETUP:-0}" | |
| if [ "$RUN_SYMFONY_RUNTIME_SETUP" = "1" ] || [ -z "$(ls -A 'var/cache/' 2>/dev/null)" ]; then | |
| php bin/console cache:clear --no-debug | |
| fi | |
| if [ "$RUN_SYMFONY_RUNTIME_SETUP" = "1" ] || [ -z "$(ls -A 'public/bundles/' 2>/dev/null)" ]; then | |
| php bin/console assets:install public --no-debug | |
| fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says this stage "warm[s] Symfony cache", but the stage only runs
composer dump-autoload/dump-envand never executesbin/console cache:clear/cache:warmup. Either update the comment to match what’s actually happening, or add an explicit cache warmup step (ideally in the builder so runtime startup doesn’t have to rebuild it).