What I went with was having both a web server (Apache/Nginx) and PHP-FPM in the same container image, held together by Supervisor: http://supervisord.org/
In my case, the Dockerfile looks a bit like the following:
# Whatever base web server image you want, Debian/Ubuntu based here
FROM .../nginx
# Bloated packages for installing dependencies and also Supervisor
RUN apt-get update \
&& apt-get -yq --no-upgrade install \
software-properties-common \
supervisor \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists /var/cache/apt/*
# Add repository for PHP 8
RUN export LC_ALL="C.UTF-8" && add-apt-repository ppa:ondrej/php
# Then we install PHP and the Nginx integration package (we use PHP-FPM)
RUN apt-get update \
&& apt-get -yq --no-upgrade install \
php8.2 php8.2-common php8.2-cli php8.2-dev php8.2-opcache ... php8.2-fpm \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists /var/cache/apt/*
# We will also need Composer for managing dependencies
RUN curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php \
&& php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=Composer
# Create directories, clear regular web server index directories
RUN mkdir -p /run/php \
&& rm -rf /var/www/html && mkdir -p /var/www/html
# Copy over config (whatever you have)
COPY ./php_nginx/etc/nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./php_nginx/var/www/html /var/www/html
COPY ./php_nginx/etc/supervisord.conf /etc/supervisord.conf
# Copy PHP config (whatever you have)
COPY ./php_nginx/etc/php/8.2/fpm/php.ini /etc/php/8.2/fpm/php.ini
COPY ./php_nginx/etc/php/8.2/fpm/php-fpm.conf /etc/php/8.2/fpm/php-fpm.conf
COPY ./php_nginx/etc/php/8.2/fpm/pool.d/www.conf /etc/php/8.2/fpm/pool.d/www.conf
# Default run script
COPY ./php_nginx/docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
CMD "/docker-entrypoint.sh"
Of course, it isn't necessarily the most idiomatic way to work with containers, but if you have health checks then it should still be fine. With a base image a little like this, you should then be able to build your own images with the code included, or use a bind mount. You can probably get images that work a bit like this pre-made, this is just how I do things, in case you're curious about what that might look like from scratch. Apache also has mod_php which would be even simpler, though generally will perform worse than PHP-FPM.
Curiously, this is also one of the few detriments of PHP in my eyes - when compared to something like Java that just spits out one .jar that can be run on anything with a compatible JDK version (at least with how things are done in the recent years vs standalone Apache Tomcat).
In my case, the Dockerfile looks a bit like the following:
Here's the entrypoint: Here's a snippet of nginx.conf, how to get *.php to be executed (put inside of a server block): And here's the Supervisor configuration: Of course, it isn't necessarily the most idiomatic way to work with containers, but if you have health checks then it should still be fine. With a base image a little like this, you should then be able to build your own images with the code included, or use a bind mount. You can probably get images that work a bit like this pre-made, this is just how I do things, in case you're curious about what that might look like from scratch. Apache also has mod_php which would be even simpler, though generally will perform worse than PHP-FPM.Curiously, this is also one of the few detriments of PHP in my eyes - when compared to something like Java that just spits out one .jar that can be run on anything with a compatible JDK version (at least with how things are done in the recent years vs standalone Apache Tomcat).