symfony-docker
symfony-docker copied to clipboard
Combined PHP + Caddy Docker image
For environment like Digital Ocean App Platform you need to setup your app as a one container.
To easily use of such service would need to combine PHP-FPM and Caddy created with the current Dockerfile.
Could it be done with feasible effort?
@back-2-95 this would require to write a complete new Dockerfile which uses for example the caddy base image and then adds all the PHP stuff.
But it's not possible to simply merge two images into one with docker (for some good reasons I guess :thinking: )
I actually did after posting this issue. Not sure how to deliver this for anyone who wants to use it, but here is it for anyone stumbling to this issue:
ARG PHP_VERSION=8.1
ARG CADDY_VERSION=2
ARG NODE_VERSION=16
FROM php:${PHP_VERSION}-fpm-alpine AS symfony_php
# persistent / runtime deps
RUN apk add --no-cache acl fcgi file gettext git gnu-libiconv
# install gnu-libiconv and set LD_PRELOAD env to make iconv work fully on Alpine image.
# see https://github.com/docker-library/php/issues/240#issuecomment-763112749
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so
ARG APCU_VERSION=5.1.21
RUN set -eux; \
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
icu-dev \
libzip-dev \
zlib-dev \
; \
\
docker-php-ext-configure zip; \
docker-php-ext-install -j$(nproc) \
pdo_mysql \
intl \
zip \
; \
pecl install \
apcu-${APCU_VERSION} \
; \
pecl clear-cache; \
docker-php-ext-enable \
apcu \
opcache \
; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-cache --virtual .phpexts-rundeps $runDeps; \
\
apk del .build-deps
COPY docker/php/docker-healthcheck.sh /usr/local/bin/docker-healthcheck
RUN chmod +x /usr/local/bin/docker-healthcheck
#HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD ["docker-healthcheck"]
RUN ln -s $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini
COPY docker/php/conf.d/symfony.prod.ini $PHP_INI_DIR/conf.d/symfony.ini
COPY docker/php/php-fpm.d/zz-docker.conf /usr/local/etc/php-fpm.d/zz-docker.conf
COPY docker/php/docker-entrypoint.sh /usr/local/bin/docker-entrypoint
RUN chmod +x /usr/local/bin/docker-entrypoint
VOLUME /var/run/php
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
ENV COMPOSER_ALLOW_SUPERUSER=1
ENV PATH="${PATH}:/root/.composer/vendor/bin"
WORKDIR /srv/app
RUN apk add --no-cache --virtual .pgsql-deps postgresql-dev; \
docker-php-ext-install -j$(nproc) pdo_pgsql; \
apk add --no-cache --virtual .pgsql-rundeps so:libpq.so.5; \
apk del .pgsql-deps
COPY . .
RUN set -eux; \
mkdir -p var/cache var/log; \
composer install --prefer-dist --no-dev --no-progress --no-scripts --no-interaction; \
composer dump-autoload --classmap-authoritative --no-dev; \
composer symfony:dump-env prod; \
composer run-script --no-dev post-install-cmd; \
chmod +x bin/console; sync
VOLUME /srv/app/var
ARG CADDY_VERSION
COPY --from=caddy:${CADDY_VERSION} /usr/bin/caddy /usr/bin/caddy
COPY docker/caddy/Caddyfile /etc/caddy/Caddyfile
EXPOSE 80
EXPOSE 443
EXPOSE 2019
ENTRYPOINT ["docker-entrypoint"]
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
FROM node:${NODE_VERSION}-alpine as asset-builder
COPY --from=symfony_php /srv/app /srv/app
WORKDIR /srv/app
RUN yarn install --frozen-lockfile
RUN yarn build
FROM symfony_php as prod-build
COPY --from=asset-builder /srv/app/public/build/ /srv/app/public/build/
Great :muscle:
So you have three steps here:
- Image
symfony_phpwith PHP and Caddy - Image
asset-builderto build the Frontend (js,css) - Image
prod-buildwith PHP and Caddy which then gets the assets - that image you deploy on your server
Also for my understanding, this Dockerfile does not build Caddy with mercure and vulcain add-ons, right?
And the docker-compose also would not work with this Dockerfile anymore (or if someone would like to use docker-compose with this file, then it needs to be adjusted as well) ?
Maybe it's worth to add this to the docs for other users as well ?
Somewhat related to this I created bake file which creates php-fpm and caddy "base images" as amd64 and arm64 variants:
PHP81_MINOR=8.1.4 docker buildx bake -f symfony/docker-bake.hcl --pull --no-cache --push
Images are here:
- https://hub.docker.com/repository/docker/druidfi/symfony-php
- https://hub.docker.com/repository/docker/druidfi/symfony-caddy
They are now just with PHP 8.1 and my project's dockerfile uses them like this:
#
# Asset builder
#
FROM node:16-alpine as asset-builder
WORKDIR /srv/app
COPY package.json postcss.config.js tailwind.config.js webpack.config.js yarn.lock ./
COPY assets ./assets
COPY templates ./templates
RUN yarn install --frozen-lockfile
RUN yarn build-prod
#
# PHP-FPM
#
FROM druidfi/symfony-php:fpm-8.1 AS symfony_php
# Only customization to base image
RUN echo "date.timezone=Europe/Helsinki" > /usr/local/etc/php/conf.d/timezone.ini
COPY . .
COPY --from=asset-builder /srv/app/public/build/ public/build/
RUN set -eux; \
mkdir -p var/cache var/log; \
composer install --prefer-dist --no-dev --no-progress --no-scripts --no-interaction; \
composer dump-autoload --classmap-authoritative --no-dev; \
composer symfony:dump-env prod; \
composer run-script --no-dev post-install-cmd; \
chmod +x bin/console; sync
#
# Caddy
#
FROM druidfi/symfony-caddy:2 AS symfony_caddy
COPY --from=symfony_php /srv/app/public public/
COPY --from=asset-builder /srv/app/public/build/ public/build/
If someone stubles on this issue, maybe ppl can test those images and can give feedback 🙏
I'm also planning to create that image including caddy+php-fpm in the same.
I'd like to add my two cents of Docker experience to this subject :wink:
If you want to run caddy and php-fpm on the same image, you will also need to run inside the image/container a process like supervisor that launches caddy and php-fpm, since you can't invoke two process on the CMD directive of Docker. Or you could create a script that launches the two process in the background.
Anyway, I understand that certain services ask to run your app in a single image/container, but in general terms, the best Docker practices says that you should avoid running more than one different process in the same image/container.
Greets. Ernesto
If you want to run caddy and php-fpm on the same image, you will also need to run inside the image/container a process like supervisor that launches caddy and php-fpm, since you can't invoke two process on the CMD directive of Docker. Or you could create a script that launches the two process in the background.
This could easily be achieved with https://github.com/Baldinof/caddy-supervisor