Sign inSign up

dmkos/php

By dmkos

Updated 20 days ago

Different container images of PHP. Currently Lighttpd on top of php:fpm.

Image
Languages & frameworks
Web servers
0

5.3K

dmkos/php repository overview

Quick reference

Source code is available at https://github.com/dmkos/php-containers

Where to file issues: https://github.com/dmkos/php-containers/issues

Images can be found here on Docker Hub and GitHub:

Lighttpd

Lighttpd web server on top of php:fpm official image. Containers are intended to use with reverse proxy such as Traefik (recommended) or HAProxy, therefore access logs are disabled. However, it is also possible to operate exposed directly to the internet.

The server is built from source and listens 9000 port (while PHP-FPM - socket).

Tags

Naming scheme follows official php:apache combinations with additional tags indicating Lighttpd versions. I suggest using a tag like 8.4-lighttpd or 8.4-lighttpd-s6.

  • 8.4-lighttpd, 8.4-lighttpd-trixie, etc. - unprivileged Debian-based image
  • 8.4-lighttpd-s6, 8.4-lighttpd-s6-trixie, etc. - s6-overlay Debian-based image
  • 8.4-lighttpd-alpine etc. - unprivileged Alpine-based image
  • 8.4-lighttpd-s6-alpine etc. - s6-overlay Alpine-based image

Usage

Differences between the image variants are shown in a table below.

unprivilegeds6
Init systemDocker CMDs6-overlay
PHP-FPM running methodmod_fastcgis6 service
USERwww-dataroot
Web-server and php-fpm pool userdepending on USERwww-data (customizable)
Write access log to stderr allowed
Graceful shutdown?
composer, unzip
php-fpm-healthcheck, cgi-fcgi

Caution

In the unprivileged image guarantee of graceful shutdown is for Lighttpd only.

s6 images are considered to be more general-purpose. The main factors in choosing the variant probably will be the USER directive and PHP-FPM graceful shutdown.

Alpine based variants instead of Debian are preferable in terms of image size minimization. However, their performance and compatibility with used software should be tested.

In order for popular PHP frameworks to work at least you need to define URL rewrite rules and override the server's document root.

Environment variables

The following environment variables are used and exposed in the dockerfile.

All variants
  • LIGHTTPD_PORT - web server port, default 9000;
  • LIGHTTPD_DOCUMENT_ROOT - web server document root, default /var/www/html. Override depending on application design;
  • HEALTHCHECK_PATH - path (URL) for container's health check. Leading slash is required. Requested resource must return HTTP code 200. By default script is polling the Lighttpd status. I recommend using a specific endpoint, e.g. /up for Laravel.
s6-overlay only
  • LIGHTTPD_MAX_FDS - maximum number of file descriptors served by web server, default 1024. Increase in case of high traffic site;
  • WWW_USER - owner of web server and php-fpm pool processes, default www-data;
  • FCGI_CONNECT - path to PHP-FPM socket, default /tmp/www.sock.
Configure Lighttpd

There are three common ways:

  1. Bind directory with local configuration files, such as rewrite rules, to /usr/local/etc/lighttpd/conf.d. I think this covers most use cases.
  2. Pass individual files to /etc/lighttpd/conf.d, especially if you need to enable some modules before fastcgi.
  3. Replace the whole /etc/lighttpd/conf.d directory with configuration written from scratch. Hope you don't have to use such radical method.

And 4th is somehow to combine 1st and 2nd ones.

Rewrite URL

E.g. rewrite URL for Symfony framework and others with the same principle:

# index.php expects original URL in PATH_INFO
url.rewrite-if-not-file = ( "" => "/index.php${url.path}${qsa}" )
IP address

When working behind a reverse proxy, use mod_extforward to determine the client's IP address:

# extract the client's "real" IP
server.modules += ( "mod_extforward" )
extforward.forwarder = (
    "10.0.0.0/8" => "trust",
    "172.16.0.0/12" => "trust",
    "192.168.0.0/16" => "trust"
)
# Traefik: that's it
# HAProxy: uncomment the following line
#extforward.hap-PROXY = "enable"

Enable the PROXY protocol in HAProxy backend settings:

backend site
    server lighty php:9000 send-proxy-v2 check
Logging

It is better to set up logging at proxy server (Traefik). Nevertheless activating access logs can be done with:

# log to container's log (stderr)
# unprivileged image only, use regular file with s6
accesslog.filename = "/proc/self/fd/2"
Compression

In case of network traffic between the servers or lack of algorithms support by proxy server (HAProxy) you can enable compression like this:

# Output compression
# https://wiki.lighttpd.net/mod_deflate
server.modules += ( "mod_deflate" )
deflate.mimetypes = ( "text/*" )
deflate.allowed-encodings = ( "zstd", "br", "gzip" )
HTTP/2 protocol

If proxy server and web server communicating by HTTP/1.1 protocol, disable the HTTP/2 support:

server.feature-flags += ("server.h2proto" => "disable")

If your web server is directly exposed to the internet, disable support of HTTP/2 over HTTP (cleartext) protocol for security reasons:

server.feature-flags += ( "server.h2c" => "disable" )
Critical changes

The 8.4.14-lighttpd-1.4.82-trixie image version has the following changes compared to first published:

  • compile Lighttpd with support of OpenSSL as well as the zstd and br compression algorithms;
  • reduce the list of index file names: index-file.names = ( "index.php", "index.html", "index.htm" )
  • leave only .php in the excluded extensions of static files: static-file.exclude-extensions = ( ".php" ).

Caution

Adapt your Lighttpd configuration in case of using another index files or additional cgi (fastcgi) modules.
PHP configuration and extensions

Compared to official php:fpm image only logging, user, and socket settings were modified, so you configure PHP and install extensions as usual.

Note

In unprivileged image you'll have to switch to `root` user and then back to `www-data`.

E.g.:

FROM dmkos/php:8.4-lighttpd

# Switch to configure PHP
USER root

# Install PHP extensions
ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN install-php-extensions \
        gd \
        intl

# Use the default production configuration
RUN cp "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# Switch back to unprivileged user (required)
USER www-data
Arbitrary user

If you're not happy with www-data for some reason (usually it is related to file permissions of your source code), here is how to create custom user.

Unprivileged image
FROM dmkos/php:8.4-lighttpd

# Switch to create user
USER root

ARG WWW_UID=1000
ARG WWW_USER=lighty
RUN set -eux; \
        useradd -m -c 'World Wide Web Owner' -u $WWW_UID $WWW_USER; \
        chown -R ${WWW_USER}:${WWW_USER} /var/www/html

# Switch to newly created user
USER $WWW_USER
s6-overlay image

The difference is that you don't need to switch to root user first but you have to change the value of WWW_USER environment variable.

FROM dmkos/php:8.4-lighttpd-s6

ARG WWW_UID=1000
ARG WWW_USER=lighty
# change environment variable accordingly
ENV WWW_USER=$WWW_USER

RUN set -eux; \
        useradd -m -c 'World Wide Web Owner' -u $WWW_UID $WWW_USER; \
        chown -R ${WWW_USER}:${WWW_USER} /var/www/html

It is possible to choose a new user, but it has some limitations and is not recommended.

# switch to the newly created user if you really want to
USER $WWW_USER
Examples

Licenses

This repository is released under the MIT license⁠.

Lighttpd is open source under the revised BSD license.

s6-overlay is open source under the ISC license.

View PHP Licensing information.

As with all Docker images, these likely also contain other software which may be under other licenses (such as Bash, etc from the base distribution, along with any direct or indirect dependencies of the primary software being contained).

Tag summary

Content type

Image

Digest

sha256:4d702cd2d

Size

174.6 MB

Last updated

20 days ago

docker pull dmkos/php:lighttpd-trixie