I like PHP, one issue which I face with PHP though is, that it is difficult to create a self-contained docker image.
With node.js or java spring boot i can build an application with an http endpoint and create a single docker image with all included easily.
With php I need 2 distinct containers, e.g., nginx, php-fpm and the code mounted on a volume to the the containers. So it seems to be more difficult for setup and continous integration etc.
I would like to have one image with php, a webserver and the code. Is there something like that for PHP?
The built in web server is awful on its own. Forget production usage, it’s hard to even use for a quick bit of E2E testing.
Unfortunately it has some really opinionated routing rules with certain file extensions, preventing you from having a dynamic URL with something like a .json or a .xml extension. Instead it will always try to look up a static file of that and serve it instead.
I can’t find the bug tracker issue for it but it was closed out with a message along the lines of “don’t use the built in web server for anything besides a toy”.
Luckily there are plenty of PHP Cli based web servers now that some other commenters have mentioned.
You can take full control over the routing using router script, then none of the default rules will apply. To be honest, I really dislike how many applications are wired around some Apache configuration or at least assume some specific hostname or path to be used for no reason. If it works with the built-in webserver, then it will work just as well with pretty much any SAPI.
Warning: This web server is designed to aid application development. It may also be useful for testing purposes or for application demonstrations that are run in controlled environments. It is not intended to be a full-featured web server. It should not be used on a public network.
the embedded server is great for dev, but useless for production. for example any url that contains a dot "." is considered to be a static file. so for example this path does not do what it's spposed to do /login.php?token=fghjjbjkkooll.rfcgg
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).
With node.js or java spring boot i can build an application with an http endpoint and create a single docker image with all included easily.
With php I need 2 distinct containers, e.g., nginx, php-fpm and the code mounted on a volume to the the containers. So it seems to be more difficult for setup and continous integration etc.
I would like to have one image with php, a webserver and the code. Is there something like that for PHP?