Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

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?



I don't really know what directed you to the nginx+fpm+volumes in the first place.

  FROM php:7.2-apache
  COPY src/ /var/www/html/
and this is it.


You want fpm for non hobby projects


Don't follow any advice to use Apache as a reverse proxy, or bundle php with a classic web server.

There are real application servers using an event loop by now, most notably Roadrunner (https://roadrunner.dev), FrankenPHP (https://frankenphp.dev), Laravel Octane (https://laravel.com/docs/10.x/octane#introduction), Swoole Bridge for Symfony (https://github.com/insidestyles/swoole-bridge-bundle).

In general, you can do a lot with OpenSwoole or Roadrunner. They are vastly superior (in a container scenario) to any other suggestion in this thread!


You can also use nginx’s unit docker container, which hosts php’s interpreter in the nginx process.

https://unit.nginx.org/installation/#installation-docker


I use RoadRunner for that purpose. It even has some amazing features you can enable as keeping the application loaded in memory between requests.

https://roadrunner.dev/


Had good success using Nginx Unit (distinct from normal nginx) for this. There's a unit-php docker image that can be used.


Yes, the apache[0] image will do what you want

[0] https://github.com/docker-library/php/blob/1c4b255f3e5ab610c...


You can't have nginx and php in the same container?


Does not docker recommend a single process story? Nginx is typically a reverse proxy in front of an application server.


That's just a generic recommendation though, really nothing stops you from having php and nginx in the same container.


PHP has had a built-in web server since version 5.

People use Apache or nginx because they want to, but because they need to.


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.


The built-in web server can only process one request at a time.


I think using the php built-in webserver is not an option for a production setting.


Correct. From the documentation:

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


Yes- apache with mod_php. It's the most common deployment by far.


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"
Here's the entrypoint:

  #!/bin/sh
  echo "Software versions..."
  nginx -V && supervisord --version

  echo "Running Supervisor..."
  supervisord --configuration=/etc/supervisord.conf
Here's a snippet of nginx.conf, how to get *.php to be executed (put inside of a server block):

  location ~ \.php$ {
      include snippets/fastcgi-php.conf;
      fastcgi_pass 127.0.0.1:9000;
  }
And here's the Supervisor configuration:

  [supervisord]
  nodaemon=true
  
  [program:php-fpm]
    command=/usr/sbin/php-fpm8.2 -c /etc/php/8.2/fpm/php-fpm.conf --nodaemonize
    stdout_logfile=/dev/stdout
    stdout_logfile_maxbytes=0
    stderr_logfile=/dev/stderr
    stderr_logfile_maxbytes=0
  
  [program:nginx]
    command=/usr/sbin/nginx
    stdout_logfile=/dev/stdout
    stdout_logfile_maxbytes=0
    stderr_logfile=/dev/stderr
    stderr_logfile_maxbytes=0
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).


Well, at least in the past you could have run apache with mod_php. And the php files should also integrateable into the image.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: