• Stars
    star
    774
  • Rank 58,703 (Top 2 %)
  • Language HCL
  • License
    MIT License
  • Created almost 7 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A set of PHP Docker images

Docker PHP Images GitHub workflow

General purpose PHP images for Docker

This repository contains a set of developer-friendly, general purpose PHP images for Docker.

  • You can enable or disable the extensions using environment variables.
  • You can also modify the php.ini settings using environment variables.
  • 2 types available: slim (no extensions preloaded) or fat (most common PHP extensions are built-in)
  • 3 variants available: CLI, apache and fpm
  • Fat images are bundled with Supercronic which is a Cron compatible task runner. Cron jobs can be configured using environment variables
  • Fat images come with Composer and Prestissimo installed
  • All variants can be installed with or without NodeJS (if you need to build your static assets).
  • Everything is done to limit file permission issues that often arise when using Docker. The image is actively tested on Linux, Windows and MacOS

Images

Name PHP version type variant NodeJS version Size
thecodingmachine/php:8.2-v4-apache 8.2.x fat apache N/A
thecodingmachine/php:8.2-v4-apache-node10 8.2.x fat apache 10.x(2)
thecodingmachine/php:8.2-v4-apache-node12 8.2.x fat apache 12.x
thecodingmachine/php:8.2-v4-apache-node14 8.2.x fat apache 14.x
thecodingmachine/php:8.2-v4-apache-node16 8.2.x fat apache 16.x
thecodingmachine/php:8.2-v4-apache-node18 8.2.x fat apache 18.x
thecodingmachine/php:8.2-v4-fpm 8.2.x fat fpm N/A
thecodingmachine/php:8.2-v4-fpm-node10 8.2.x fat fpm 10.x(2)
thecodingmachine/php:8.2-v4-fpm-node12 8.2.x fat fpm 12.x
thecodingmachine/php:8.2-v4-fpm-node14 8.2.x fat fpm 14.x
thecodingmachine/php:8.2-v4-fpm-node16 8.2.x fat fpm 16.x
thecodingmachine/php:8.2-v4-fpm-node18 8.2.x fat fpm 18.x
thecodingmachine/php:8.2-v4-cli 8.2.x fat cli N/A
thecodingmachine/php:8.2-v4-cli-node10 8.2.x fat cli 10.x(2)
thecodingmachine/php:8.2-v4-cli-node12 8.2.x fat cli 12.x
thecodingmachine/php:8.2-v4-cli-node14 8.2.x fat cli 14.x
thecodingmachine/php:8.2-v4-cli-node16 8.2.x fat cli 16.x
thecodingmachine/php:8.2-v4-cli-node18 8.2.x fat cli 18.x
thecodingmachine/php:8.2-v4-slim-apache 8.2.x slim apache N/A
thecodingmachine/php:8.2-v4-slim-fpm 8.2.x slim fpm N/A
thecodingmachine/php:8.2-v4-slim-cli 8.2.x slim cli N/A
thecodingmachine/php:8.1-v4-apache 8.1.x fat apache N/A
thecodingmachine/php:8.1-v4-apache-node10 8.1.x fat apache 10.x(2)
thecodingmachine/php:8.1-v4-apache-node12 8.1.x fat apache 12.x
thecodingmachine/php:8.1-v4-apache-node14 8.1.x fat apache 14.x
thecodingmachine/php:8.1-v4-apache-node16 8.1.x fat apache 16.x
thecodingmachine/php:8.1-v4-apache-node18 8.1.x fat apache 18.x
thecodingmachine/php:8.1-v4-fpm 8.1.x fat fpm N/A
thecodingmachine/php:8.1-v4-fpm-node10 8.1.x fat fpm 10.x(2)
thecodingmachine/php:8.1-v4-fpm-node12 8.1.x fat fpm 12.x
thecodingmachine/php:8.1-v4-fpm-node14 8.1.x fat fpm 14.x
thecodingmachine/php:8.1-v4-fpm-node16 8.1.x fat fpm 16.x
thecodingmachine/php:8.1-v4-fpm-node18 8.1.x fat fpm 18.x
thecodingmachine/php:8.1-v4-cli 8.1.x fat cli N/A
thecodingmachine/php:8.1-v4-cli-node10 8.1.x fat cli 10.x(2)
thecodingmachine/php:8.1-v4-cli-node12 8.1.x fat cli 12.x
thecodingmachine/php:8.1-v4-cli-node14 8.1.x fat cli 14.x
thecodingmachine/php:8.1-v4-cli-node16 8.1.x fat cli 16.x
thecodingmachine/php:8.1-v4-cli-node18 8.1.x fat cli 18.x
thecodingmachine/php:8.1-v4-slim-apache 8.1.x slim apache N/A
thecodingmachine/php:8.1-v4-slim-fpm 8.1.x slim fpm N/A
thecodingmachine/php:8.1-v4-slim-cli 8.1.x slim cli N/A
thecodingmachine/php:8.0-v4-apache 8.0.x fat apache N/A
thecodingmachine/php:8.0-v4-apache-node10 8.0.x fat apache 10.x(2)
thecodingmachine/php:8.0-v4-apache-node12 8.0.x fat apache 12.x
thecodingmachine/php:8.0-v4-apache-node14 8.0.x fat apache 14.x
thecodingmachine/php:8.0-v4-apache-node16 8.0.x fat apache 16.x
thecodingmachine/php:8.0-v4-apache-node18 8.0.x fat apache 18.x
thecodingmachine/php:8.0-v4-fpm 8.0.x fat fpm N/A
thecodingmachine/php:8.0-v4-fpm-node10 8.0.x fat fpm 10.x(2)
thecodingmachine/php:8.0-v4-fpm-node12 8.0.x fat fpm 12.x
thecodingmachine/php:8.0-v4-fpm-node14 8.0.x fat fpm 14.x
thecodingmachine/php:8.0-v4-fpm-node16 8.0.x fat fpm 16.x
thecodingmachine/php:8.0-v4-fpm-node18 8.0.x fat fpm 18.x
thecodingmachine/php:8.0-v4-cli 8.0.x fat cli N/A
thecodingmachine/php:8.0-v4-cli-node10 8.0.x fat cli 10.x(2)
thecodingmachine/php:8.0-v4-cli-node12 8.0.x fat cli 12.x
thecodingmachine/php:8.0-v4-cli-node14 8.0.x fat cli 14.x
thecodingmachine/php:8.0-v4-cli-node16 8.0.x fat cli 16.x
thecodingmachine/php:8.0-v4-cli-node18 8.0.x fat cli 18.x
thecodingmachine/php:8.0-v4-slim-apache 8.0.x slim apache N/A
thecodingmachine/php:8.0-v4-slim-fpm 8.0.x slim fpm N/A
thecodingmachine/php:8.0-v4-slim-cli 8.0.x slim cli N/A
thecodingmachine/php:7.4-v4-apache 7.4.x fat apache N/A
thecodingmachine/php:7.4-v4-apache-node10 7.4.x fat apache 10.x(2)
thecodingmachine/php:7.4-v4-apache-node12 7.4.x fat apache 12.x
thecodingmachine/php:7.4-v4-apache-node14 7.4.x fat apache 14.x
thecodingmachine/php:7.4-v4-apache-node16 7.4.x fat apache 16.x
thecodingmachine/php:7.4-v4-apache-node18 7.4.x fat apache 18.x
thecodingmachine/php:7.4-v4-fpm 7.4.x fat fpm N/A
thecodingmachine/php:7.4-v4-fpm-node10 7.4.x fat fpm 10.x(2)
thecodingmachine/php:7.4-v4-fpm-node12 7.4.x fat fpm 12.x
thecodingmachine/php:7.4-v4-fpm-node14 7.4.x fat fpm 14.x
thecodingmachine/php:7.4-v4-fpm-node16 7.4.x fat fpm 16.x
thecodingmachine/php:7.4-v4-fpm-node18 7.4.x fat fpm 18.x
thecodingmachine/php:7.4-v4-cli 7.4.x fat cli N/A
thecodingmachine/php:7.4-v4-cli-node10 7.4.x fat cli 10.x(2)
thecodingmachine/php:7.4-v4-cli-node12 7.4.x fat cli 12.x
thecodingmachine/php:7.4-v4-cli-node14 7.4.x fat cli 14.x
thecodingmachine/php:7.4-v4-cli-node16 7.4.x fat cli 16.x
thecodingmachine/php:7.4-v4-cli-node18 7.4.x fat cli 18.x
thecodingmachine/php:7.4-v4-slim-apache 7.4.x slim apache N/A
thecodingmachine/php:7.4-v4-slim-fpm 7.4.x slim fpm N/A
thecodingmachine/php:7.4-v4-slim-cli 7.4.x slim cli N/A
thecodingmachine/php:7.3-v4-apache 7.3.x(1) fat apache N/A
thecodingmachine/php:7.3-v4-apache-node10 7.3.x(1) fat apache 10.x(2)
thecodingmachine/php:7.3-v4-apache-node12 7.3.x(1) fat apache 12.x
thecodingmachine/php:7.3-v4-apache-node14 7.3.x(1) fat apache 14.x
thecodingmachine/php:7.3-v4-apache-node16 7.3.x(1) fat apache 16.x
thecodingmachine/php:7.3-v4-apache-node18 7.3.x(1) fat apache 18.x
thecodingmachine/php:7.3-v4-fpm 7.3.x(1) fat fpm N/A
thecodingmachine/php:7.3-v4-fpm-node10 7.3.x(1) fat fpm 10.x(2)
thecodingmachine/php:7.3-v4-fpm-node12 7.3.x(1) fat fpm 12.x
thecodingmachine/php:7.3-v4-fpm-node14 7.3.x(1) fat fpm 14.x
thecodingmachine/php:7.3-v4-fpm-node16 7.3.x(1) fat fpm 16.x
thecodingmachine/php:7.3-v4-fpm-node18 7.3.x(1) fat fpm 18.x
thecodingmachine/php:7.3-v4-cli 7.3.x(1) fat cli N/A
thecodingmachine/php:7.3-v4-cli-node10 7.3.x(1) fat cli 10.x(2)
thecodingmachine/php:7.3-v4-cli-node12 7.3.x(1) fat cli 12.x
thecodingmachine/php:7.3-v4-cli-node14 7.3.x(1) fat cli 14.x
thecodingmachine/php:7.3-v4-cli-node16 7.3.x(1) fat cli 16.x
thecodingmachine/php:7.3-v4-cli-node18 7.3.x(1) fat cli 18.x
thecodingmachine/php:7.3-v4-slim-apache 7.3.x(1) slim apache N/A
thecodingmachine/php:7.3-v4-slim-fpm 7.3.x(1) slim fpm N/A
thecodingmachine/php:7.3-v4-slim-cli 7.3.x(1) slim cli N/A
thecodingmachine/php:7.2-v4-apache 7.2.x(1) fat apache N/A
thecodingmachine/php:7.2-v4-apache-node10 7.2.x(1) fat apache 10.x(2)
thecodingmachine/php:7.2-v4-apache-node12 7.2.x(1) fat apache 12.x
thecodingmachine/php:7.2-v4-apache-node14 7.2.x(1) fat apache 14.x
thecodingmachine/php:7.2-v4-apache-node16 7.2.x(1) fat apache 16.x
thecodingmachine/php:7.2-v4-apache-node18 7.2.x(1) fat apache 18.x
thecodingmachine/php:7.2-v4-fpm 7.2.x(1) fat fpm N/A
thecodingmachine/php:7.2-v4-fpm-node10 7.2.x(1) fat fpm 10.x(2)
thecodingmachine/php:7.2-v4-fpm-node12 7.2.x(1) fat fpm 12.x
thecodingmachine/php:7.2-v4-fpm-node14 7.2.x(1) fat fpm 14.x
thecodingmachine/php:7.2-v4-fpm-node16 7.2.x(1) fat fpm 16.x
thecodingmachine/php:7.2-v4-fpm-node18 7.2.x(1) fat fpm 18.x
thecodingmachine/php:7.2-v4-cli 7.2.x(1) fat cli N/A
thecodingmachine/php:7.2-v4-cli-node10 7.2.x(1) fat cli 10.x(2)
thecodingmachine/php:7.2-v4-cli-node12 7.2.x(1) fat cli 12.x
thecodingmachine/php:7.2-v4-cli-node14 7.2.x(1) fat cli 14.x
thecodingmachine/php:7.2-v4-cli-node16 7.2.x(1) fat cli 16.x
thecodingmachine/php:7.2-v4-cli-node18 7.2.x(1) fat cli 18.x
thecodingmachine/php:7.2-v4-slim-apache 7.2.x(1) slim apache N/A
thecodingmachine/php:7.2-v4-slim-fpm 7.2.x(1) slim fpm N/A
thecodingmachine/php:7.2-v4-slim-cli 7.2.x(1) slim cli N/A

Note: we also tag patch releases of PHP versions. So you can specify a specific patch release using thecodingmachine/php:8.0.2-v4-cli for instance. However, unless you have a very specific need (for instance if the latest patch release of PHP introduced regressions), believe you have no valid reason to ask explicitly for 8.0.2 for instance. When 8.0.3 is out, you certainly want to upgrade automatically to this patch release since patch releases contain only bugfixes. Also, we automatically rebuild X.Y images every week, but only the latest X.Y.Z patch release gets a rebuild. The other patch releases are frozen in time and will contain bugs and security issues. So use those with great care.

[Major].[minor] images are automatically updated when a new patch version of PHP is released, so the PHP 7.4 image will always contain the most up-to-date version of the PHP 7.4.x branch.

Usage

These images are based on the official PHP image.

Example with CLI:

$ docker run -it --rm --name my-running-script -v "$PWD":/usr/src/app thecodingmachine/php:8.2-v4-cli php your-script.php

Example with Apache:

$ docker run -p 80:80 --rm --name my-apache-php-app -v "$PWD":/var/www/html thecodingmachine/php:8.2-v4-apache

Example with PHP-FPM:

$ docker run -p 9000:9000 --rm --name my-php-fpm -v "$PWD":/var/www/html thecodingmachine/php:8.2-v4-fpm

Example with Apache + Node 14.x in a Dockerfile:

Dockerfile

FROM thecodingmachine/php:8.2-v4-apache-node14

COPY src/ /var/www/html/
RUN composer install
RUN npm install
RUN npm run build

Extensions available

This image comes with 2 "types": the slim and the fat image.

These extensions are enabled by default in slim image: calendar ctype curl date dom exif fileinfo filter ftp gettext iconv json mbstring opcache openssl pcntl pcre PDO Phar posix readline shmop Reflection session shmop SimpleXML sockets sodium SPL sysvmsg sysvsem sysvshm tokenizer xml xmlreader xmlwriter xsl zip

This list can be outdated, you can verify by executing : docker run --rm -it thecodingmachine/php:8.2-v4-slim-cli php -m

The slim image provides a simple way to install the other extensions. You would typically use the "slim" image in a Dockerfile when building your own custom image.

The fat image contains the most commonly used extensions. You would typically use it in a local or CI environment.

Fat image

Below is a list of extensions available in this image:

Enabled by default (in addition to extensions enabled in Slim image): apcu, hash, iconv, igbinary, mysqli, mysqlnd, redis, soap, xsl, zlib and all enabled in slim.

Available (can be enabled using environment variables): amqp ast bcmath blackfire bz2 dba ds enchant ev event exif ffi mailparse msgpack gd gettext gmp gnupg grpc igbinary imagick imap intl ldap mcrypt memcached mongodb pcov pdo_dblib pdo_pgsql pdo_sqlite pgsql pspell shmop snmp sockets sqlite3 swoole tidy uploadprogress uuid weakref(-beta) xdebug xmlrpc xsl yaml

This list can be outdated, you can verify by executing : docker run --rm -it thecodingmachine/php:8.2-v4-cli php -m

Note:

  • mcrypt is not available anymore in PHP 7.3+
  • weakref is not compatible with PHP 7.3+ (but weak references were added to the PHP core in PHP 7.4)
  • event, gnupg are not available in PHP 8.0+
  • gettext, ev, swoole are not available in PHP 8.1+
  • ev, rdkafka, snmp, swoole are not available in all ARM64 images (build time is too long : it's possible to install manually as required)
  • ffi is only available in PHP 7.4+

Enabling/disabling extensions in the fat image

You can enable/disable extensions using the PHP_EXTENSION_[extension_name] environment variable.

For instance:

version: '3'
services:
  my_app:
    image: thecodingmachine/php:8.2-v4-apache-node16
    environment:
      # Enable the PostgreSQL extension
      PHP_EXTENSION_PGSQL: 1
      # Disable the Mysqli extension (otherwise it is enabled by default)
      PHP_EXTENSION_MYSQLI: 0

As an alternative, you can use the PHP_EXTENSIONS global variable:

PHP_EXTENSIONS=pgsql gettext imap

Compiling extensions in the slim image

If you are using the slim image, you can automatically compile the extensions using the PHP_EXTENSIONS ARG in your Dockerfile.

ARG PHP_EXTENSIONS="apcu mysqli pdo_mysql redis soap"
FROM thecodingmachine/php:8.2-v4-slim-apache
# The build will automatically trigger the download and compilation
# of the extensions (thanks to a ONBUILD hook in the slim image)

Beware :

  • The ARG PHP_EXTENSIONS command must be written before the FROM. This is not a typo.
  • ARG PHP_EXTENSIONS="" it's not the same as ENV PHP_EXTENSIONS=""
  • You can't use ARG PHP_EXTENSION_MYEXT="" like the fat image.
  • Heads up: if you are using multistage builds, the "ARG" variable must be put at the very top of the file (before the first FROM):
# The PHP_EXTENSIONS ARG will apply to the "slim" image
ARG PHP_EXTENSIONS="apcu mysqli pdo_mysql soap"

FROM thecodingmachine/php:8.2-v4-apache-node16 AS builder

COPY --chown=docker:docker sources/web .
RUN composer install &&\
    yarn install &&\
    yarn build

# The slim image will automatically build the extensions from the list provided at the very top of the file.
FROM thecodingmachine/php:7.2-v4-slim-apache

ENV APP_ENV=prod \
    APACHE_DOCUMENT_ROOT=public/

COPY --from=builder /var/www/html .

In the sample above, we use the fat image to perform a "yarn build", but copy the result in a slim image that does not contain Node, and contains only required extensions.

Setting parameters in php.ini

By default, the base php.ini file used is the development php.ini file that comes with PHP.

You can use the production php.ini file using the TEMPLATE_PHP_INI environment variable:

# Use the production php.ini file as a base
TEMPLATE_PHP_INI=production

You can override parameters in php.ini using the PHP_INI_XXX environment variables:

version: '3'
services:
  my_app:
    image: thecodingmachine/php:8.2-v4-apache-node16
    environment:
      # set the parameter memory_limit=1g
      PHP_INI_MEMORY_LIMIT: 1g
      # set the parameter error_reporting=EALL
      PHP_INI_ERROR_REPORTING: E_ALL

Absolutely all php.ini parameters can be set.

Internally, the image will map all environment variables starting with PHP_INI_.

If your php.ini parameter contains a dot ("."), you can replace it with a double underscore ("__").

For instance:

# Will set the parameter xdebug.remote_autostart=1
PHP_INI_XDEBUG__REMOTE_AUTOSTART=1

Default working directory

The working directory (the directory in which you should mount/copy your application) depends on the image variant you are using:

Variant Working directory
cli /usr/src/app
apache /var/www/html
fpm /var/www/html

Changing Apache document root

For the apache variant, you can change the document root of Apache (i.e. your "public" directory) by using the APACHE_DOCUMENT_ROOT variable:

# The root of your website is in the "public" directory:
APACHE_DOCUMENT_ROOT=public/

If the APACHE_DOCUMENT_ROOT starts with a "/", it will be considered an absolute path. If the APACHE_DOCUMENT_ROOT does not starts with a "/", it will be a path relative to "/var/www/html".

# These 2 variables are identical
APACHE_DOCUMENT_ROOT=public/
APACHE_DOCUMENT_ROOT=/var/www/html/public

Enabling/disabling Apache extensions

You can enable/disable Apache extensions using the APACHE_EXTENSION_[extension_name] environment variable.

For instance:

version: '3'
services:
  my_app:
    image: thecodingmachine/php:8.2-v4-apache-node16
    environment:
      # Enable the DAV extension for Apache
      APACHE_EXTENSION_DAV: 1
      # Enable the SSL extension for Apache
      APACHE_EXTENSION_SSL: 1

As an alternative, you can use the APACHE_EXTENSIONS global variable:

APACHE_EXTENSIONS="dav ssl"

Apache modules enabled by default: access_compat alias auth_basic authn_core authn_file authz_core authz_host authz_user autoindex deflate dir env expires filter mime mpm_prefork negotiation php8.0 (depend of your active version) reqtimeout rewrite setenvif status

Apache modules available: access_compat actions alias allowmethods asis auth_basic auth_digest auth_form authn_anon authn_core authn_dbd authn_dbm authn_file authn_socache authnz_fcgi authnz_ldap authz_core authz_dbd authz_dbm authz_groupfile authz_host authz_owner authz_user autoindex brotli buffer cache cache_disk cache_socache cern_meta cgi cgid charset_lite data dav dav_fs dav_lock dbd deflate dialup dir dump_io echo env ext_filter expires file_cache filter headers heartbeat heartmonitor http2 ident imagemap include info lbmethod_bybusyness lbmethod_byrequests lbmethod_bytraffic lbmethod_heartbeat ldap log_debug log_forensic lua macro md mime mime_magic mpm_event mpm_prefork mpm_worker negotiation php8.0 (depend of your active version) proxy proxy_ajp proxy_balancer proxy_connect proxy_express proxy_fcgi proxy_fdpass proxy_ftp proxy_hcheck proxy_html proxy_http proxy_http2 proxy_scgi proxy_wstunnel ratelimit reflector remoteip reqtimeout request rewrite sed session session_cookie session_crypto session_dbd setenvif slotmem_plain slotmem_shm socache_dbm socache_memcache socache_redis socache_shmcb speling ssl status substitute suexec unique_id userdir usertrack vhost_alias xml2enc

This list can be outdated, you can verify by executing : docker run --rm -it thecodingmachine/php:8.2-v4-slim-apache a2enmod

Debugging

To enable XDebug you simply have to set the environment variable:

PHP_EXTENSION_XDEBUG=1

If you enable XDebug, the image will do its best to configure the xdebug.client_host to point back to your Docker host.

Behind the scenes, the image will:

  • set the parameter xdebug.mode=debug
  • if you are using a Linux machine, the xdebug.client_host IP will point to your Docker gateway
  • if you are using a Windows or MaxOS machine, the xdebug.client_host IP will point to host.docker.internal or docker.for.mac.localhost

If you want to debug directly inside your container (for example if you're using VSCode devcontainers) you can overwrite the xdebug.client_host value by setting the following environment variable:

XDEBUG_CLIENT_HOST=127.0.0.1

In that case the manually set value takes precedence over the mentioned ones above.

NodeJS

The fat images come with a Node variant. You can use Node 10, 12, 14 or 16. If you need a Node 8 variant, use thecodingmachine/php v3 images. If you need a Node 6 variant, use thecodingmachine/php v1 images.

If you use the slim images, you can install a NodeJS version with a simple ARG during the build:

ARG NODE_VERSION=14
FROM thecodingmachine/php:8.2-v4-slim-apache
# The build will automatically trigger the download of Node 14
# (thanks to a ONBUILD hook in the slim image)

Beware! The ARG NODE_VERSION command must be written before the FROM. This is not a typo.

NODE_VERSION can take any valid node versions (from 6 to 11 at the time of writing this README)

Permissions

Ever faced file permission issues with Docker? Good news, this is a thing of the past!

If you are used to running Docker containers with the base PHP image, you probably noticed that when running commands (like composer install) within the container, files are associated to the root user. This is because the base user of the image is "root".

When you mount your project directory into /var/www/html, it would be great if the default user used by Docker could be your current host user.

The problem with Docker is that the container and the host do not share the same list of users. For instance, you might be logged in on your host computer as superdev (ID: 1000), and the container has no user whose ID is 1000.

The thecodingmachine/php images solve this issue with a bit of black magic:

The image contains a user named docker. On container startup, the startup script will look at the owner of the working directory (/var/www/html for Apache/PHP-FPM, or /usr/src/app for CLI). The script will then assume that you want to run commands as this user. So it will dynamically change the ID of the docker user to match the ID of the current working directory user.

Furthermore, the image is changing the Apache default user/group to be docker/docker (instead if www-data/www-data). So Apache will run with the same rights as the user on your host.

The direct result is that, in development:

  • Your PHP application can edit any file
  • Your container can edit any file
  • You can still edit any file created by Apache or by the container in CLI

Using this image in production

By changing the Apache user to be docker:docker, we are lowering the security. This is OK for a development environment, but this should be avoided in production. Indeed, in production, Apache should not be allowed to edit PHP files of your application. If for some reason, an attacker manages to change PHP files using a security hole, he could then run any PHP script by editing the PHP files of your application.

In production, you want to change back the Apache user to www-data.

This can be done easily:

Dockerfile

FROM thecodingmachine/php:8.2-v4-apache

# ...

# Change back Apache user and group to www-data
ENV APACHE_RUN_USER=www-data \
    APACHE_RUN_GROUP=www-data

Setting up CRON jobs

You can set up CRON jobs using environment variables too.

To do this, you need to configure 3 variables:

# configure the user that will run cron (defaults to root)
CRON_USER=root
# configure the schedule for the cron job (here: run every minute)
CRON_SCHEDULE=* * * * *
# last but not least, configure the command
CRON_COMMAND=vendor/bin/console do:stuff

By default, CRON output will be redirected to Docker output.

If you have more than one job to run, you can suffix your environment variable with the same string. For instance:

CRON_USER_1=root
CRON_SCHEDULE_1=* * * * *
CRON_COMMAND_1=vendor/bin/console do:stuff

CRON_USER_2=www-data
CRON_SCHEDULE_2=0 3 * * *
CRON_COMMAND_2=vendor/bin/console other:stuff

Cron is installed by default in the fat images. If you are using the "slim" images, you need to install it by passing a single argument before the "FROM" clause in your Dockerfile:

ARG INSTALL_CRON=1
FROM thecodingmachine/php:8.2-v4-slim-apache
# The build triggers automatically the installation of Cron

Important: The cron runner we use is "Supercronic" and not the orginial "cron" that has a number of issues with containers. Even with Supercronic, the architecture of cron was never designed with Docker in mind (Cron is way older than Docker). It will run correctly on your container. If at some point you want to scale and add more containers, it will run on all your containers. At that point, if you only want to run a Cron task once for your application (and not once per container), you might want to have a look at alternative solutions like Tasker or use the native features of your orchestrator (if you use Kubernetes, you have a native task runner available), or one of the many other alternatives.

Please notice that by default, containers are running in the UTC timezone. So your CRONs will run at UTC time. If you want to change a timezone in a container, you can use the TZ environment variable.

# Run this cron at 1 am, Paris time
TZ=Europe/Paris
CRON_SCHEDULE_1=0 1 * * *
CRON_COMMAND_1=vendor/bin/console do:stuff

Supercronic options

To specify Supercronic options you can set the SUPERCRONIC_OPTIONS environment variable.

This can be used to enable duplicate jobs. Per default, Supercronic will wait for a given job to finish before that job is scheduled again.
With the option -overlapping Supercronic will run duplicate instances of the jobs instead of waiting for them.

SUPERCRONIC_OPTIONS=-overlapping

# Or multiple options
SUPERCRONIC_OPTIONS=-overlapping -debug

For more options see see the Supercronic Documentation.

Launching commands on container startup

You can launch commands on container startup using the STARTUP_COMMAND_XXX environment variables. This can be very helpful to install dependencies or apply database patches for instance:

STARTUP_COMMAND_1=composer install
STARTUP_COMMAND_2=vendor/bin/doctrine orm:schema-tool:update 

As an alternative, the images will look into the container for an executable file named /etc/container/startup.sh.

If such a file is mounted in the image, it will be executed on container startup.

docker run -it --rm --name my-running-script -v "$PWD":/usr/src/myapp -w /usr/src/myapp \ 
       -v $PWD/my-startup-script.sh:/etc/container/startup.sh thecodingmachine/php:8.2-v4-cli php your-script.php 

Using the CLI variant

The CLI images (thecodingmachine/php:8.2-v4-cli) expect a command to be passed in parameter. You should override the Docker "command".

Important! You should not override the Docker "entrypoint".

Usage in a Dockerfile:

FROM thecodingmachine/php:8.2-v4-cli

CMD ["php", "myprogram.php", "some_param"]

Usage with Docker compose:

docker-compose.yml

version: '3'
services:
  my_app:
    image: thecodingmachine/php:8.2-v4-cli
    command: php myprogram.php some_param

Registering SSH private keys

If your PHP project as a dependency on a package stored in a private GIT repository, your composer install commands will not work unless you register your private key in the container.

You have several options to do this.

Option 1: mount your keys in the container directly

This option is the easiest way to go if you are using the image on a development environment.

docker-compose.yml

version: '3'
services:
  my_app:
    image: thecodingmachine/php:8.2-v4-apache-node16
    volumes:
      - ~/.ssh:/home/docker/.ssh

Option 2: store the keys from environment variables or build arguments

Look at this option if you are building a Dockerfile from this image.

The first thing to do is to get the signature of the server you want to connect to.

$ ssh-keyscan myserver.com

Copy the output and put it in an environment variable. We assume the content is stored in $SSH_KNOWN_HOSTS.

Now, let's write a Dockerfile.

Dockerfile

FROM thecodingmachine/php:8.2-v4-apache

ARG SSH_PRIVATE_KEY
ARG SSH_KNOWN_HOSTS

# Let's register the private key
RUN ssh-add <(echo "$SSH_PRIVATE_KEY")
# Let's add the server to the list of known hosts.
RUN echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts

Finally, when triggering the build, you must pass the 2 variables as build arguments:

$ docker build -t my_image --build-arg SSH_PRIVATE_KEY="$SSH_PRIVATE_KEY" --build-arg SSH_KNOWN_HOSTS="$SSH_KNOWN_HOSTS" .

Usage in Kubernetes

If you plan to use this image in Kubernetes, please be aware that the image internally uses sudo. This is because the default user (docker) needs to be able to edit php config files as root.

Kubernetes has a security setting (allowPrivilegeEscalation) that can disallow the use of sudo. The use of this flag breaks the image and in the logs, you will find the message:

sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?

Please be sure that this option is never set to false:

apiVersion: v1
kind: Pod
# ...
spec:
  containers:
  - name: foobar
    image: thecodingmachine/php:8.2-v4-apache
    securityContext:
      allowPrivilegeEscalation: true # never use "false" here.

Profiling with Blackfire

This image comes with the Blackfire PHP probe. You can install it using:

PHP_EXTENSION_BLACKFIRE=1

By default, the image expects that the blackfire agent is started in another container.

Your docker-compose.yml file will typically look like this:

docker-compose.yml

version: '3.3'
services:
  php:
    image: thecodingmachine/php:8.2-v4-apache
    ports:
      - "80:80"
    environment:
      PHP_EXTENSION_BLACKFIRE: 1
  blackfire:
    image: blackfire/blackfire
    environment:
        # Exposes the host BLACKFIRE_SERVER_ID and TOKEN environment variables.
        - BLACKFIRE_SERVER_ID
        - BLACKFIRE_SERVER_TOKEN
        # You can also use global environment credentials :
        # BLACKFIRE_SERVER_ID: SERVER-ID
        # BLACKFIRE_SERVER_TOKEN: SERVER-TOKEN

See Blackfire Docker documentation for more information.

The image assumes that the Blackfire agent is accessible via the blackfire URL (like in the exemple above). If for some reason, the container name is not "blackfire", you can customize the agent URL with the BLACKFIRE_AGENT environment variable:

docker-compose.yml

version: '3.3'
services:
  php:
    image: thecodingmachine/php:8.2-v4-apache
    environment:
      PHP_EXTENSION_BLACKFIRE: 1
      BLACKFIRE_AGENT: myblackfire
    # ...
  myblackfire:
    image: blackfire/blackfire
    environment:
        # ...

Migrating from older image versions

Check the migration notes.

Contributing

There is one branch per minor PHP version and version of the image.

Please submit your pull requests to the lowest branch where is applies.

The Dockerfiles and the README are generated from a template using Orbit.

If you want to modify a Dockerfile or the README, you should instead edit the utils/Dockerfile.blueprint or utils/README.blueprint.md and then run the command:

$ orbit run generate

This command will generate all the files from the "blueprint" templates.

You can then test your changes using the build-and-test.sh command:

PHP_VERSION=8.2 BRANCH=v4 VARIANT=apache ./build-and-test.sh

Additional environment in build-and-test.sh

  • BUILDER: either build or buildx depending on your configuration. Defaults to build
  • BLACKFIRE_VERSION: defaults to 1. You can install v2 if you're feeling adventurous by specifying 2 as a value.
  • PLATFORM: Docker will default to your architecture for building images. However, if you have QEMU set up in your machine, you can try building for another architecture like linux/arm64

Only one platform at a time is supported during the build and test script execution.

APPLE SILICON CONSIDERATIONS

Filesystem management works differently in Apple's macOS, so, if you're trying to build a linux/arm64 image (that is best suited for using in a M1/M2 Mac than a linux/amd64 one), there's a high likelihood that the filesystem user and permissions with busybox are going to fail.

Although the test fails, when using the built image, everything works as expected.

Run a virtual machine with linux/arm64 with Docker installed in it and, then, build and test the image. You'll take advantage of the ARM speed and will also be able to run the unit tests properly.

Adding additional images

To add a new version (php, node, apache, ...), please edit the following files :

  • utils/README.blueprint.md
    • Add your image in this section: Images
  • orbit.yml: Your image in generation task
  • .travis.yml: To check the new image
  • build-and-test.sh: Add your image in test

Special thanks

These images have been strongly inspired by tetraweb/php.

More Repositories

1

react-native-boilerplate

A React Native template for building solid applications 🐙, using JavaScript 💛 or Typescript 💙 (you choose).
TypeScript
4,775
star
2

safe

All PHP functions, rewritten to throw exceptions instead of returning false
PHP
2,360
star
3

graphqlite

Use PHP Attributes/Annotations to declare your GraphQL API
MDX
535
star
4

phpstan-strict-rules

A set of additional rules for PHPStan based on best practices followed at TheCodingMachine
PHP
273
star
5

kickoff-docker-php

🐳 🐘 🚀 Easily setup a PHP project with Docker
Shell
208
star
6

symfony-vuejs

Source code of the tutorial "Building a single-page application with Symfony 4 and Vue.js"
PHP
178
star
7

tdbm

The Database Machine is a PHP ORM that requires no configuration. The object model is deduced from the database model.
PHP
119
star
8

nodejs-installer

An installer package that let's you install NodeJS and NPM as a Composer dependency.
PHP
108
star
9

safe8

All PHP functions, rewritten to throw exceptions instead of returning false, now for php8
PHP
106
star
10

gotenberg-php-client

PHP client for the Gotenberg API
PHP
104
star
11

symfony-boilerplate

An example of an application built with Symfony 5, GraphQL and Nuxt.js
PHP
103
star
12

discovery

Publish and discover assets in your PHP projects.
PHP
101
star
13

phpstan-safe-rule

A PHPStan rule to be used with the thecodingmachine/safe package
PHP
55
star
14

best-practices

This repository contains the files to generate the http://bestpractices.thecodingmachine.com website
Less
53
star
15

mouf

The Mouf PHP framework: an open-source PHP framework providing an easy way to download, install, use and reuse components, with a graphical user interface.
PHP
50
star
16

gotenberg-go-client

Go client for the Gotenberg API
Go
47
star
17

gitlab-registry-cleaner

A simple Docker image to be used in Gitlab CI to easily delete images in the Gitlab registry
Shell
44
star
18

packanalyst

Packanalyst is a service that let's you browse in any PHP class / interface / trait defined in Packagist
JavaScript
35
star
19

graphqlite-bundle

A Symfony bundle for thecodingmachine/graphqlite.
PHP
34
star
20

dbal-fluid-schema-builder

Build and modify your database schema using Doctrine DBAL and a fluid syntax.
PHP
25
star
21

symfony-middleware

This package provides a StackPHP middleware that can be used to use a Symfony application as a middleware (instead of an app)
PHP
23
star
22

html.widgets.statsgrid

This PHP package contains a HTML pivot table. You provide it with a data set and the list of columns and rows and it will display a nice pivot table.
PHP
22
star
23

magic-query

A very clever library to use SQL prepared statement with a variable number of parameters... and much more!
PHP
22
star
24

redux-toolkit-wrapper

Redux-toolkit wrapper used to write less code regarding classic CRUD operations.
TypeScript
19
star
25

rnb-plugin-typescript

This plugin allow thecodingmachine react-native-boilerplate 🐙 users to translate the boilerplate from Javascript 💛 to Typescript 💙
TypeScript
18
star
26

yaml-tools

A set of CLI tools to manipulate YAML files (merge, edit, etc...)
Python
18
star
27

symfony-psr15-bridge

A bridge between Symfony middlewares (StackPHP) and http-interop middlewares for converting Symfony Http abstractions to PSR-15 and back.
PHP
17
star
28

graphqlite-laravel

A Laravel service provider package to help you get started with GraphQLite in Laravel.
PHP
16
star
29

picotainer

A minimalist PHP dependency injection container compatible with ContainerInterop
PHP
15
star
30

deeployer

A tool to ease the creation of environments using docker-compose or Kubernetes
PHP
14
star
31

whoops-stackphp

This package contains a StackPHP middleware that catches all exceptions and redirects those to the Whoops error handling library.
PHP
14
star
32

graphql-controllers

Write your GraphQL queries in simple to write controllers (using webonix/graphql-php).
PHP
12
star
33

database.tdbm

The Database Machine is a PHP ORM that requires no configuration. The object model is deduced at runtime from the database model.
PHP
11
star
34

silex-middleware

This package provides a StackPHP middleware that can be used to plug a Silex application
PHP
11
star
35

docker-images-nodejs

A set of Node.js Docker images
Shell
10
star
36

yaco

YACO (Yet Another COmpiler) is a PHP tool that generates a PHP container based on entry definitions.
PHP
10
star
37

classname-mapper

Provides a way to find in which PHP files a class will be looked upon.
PHP
10
star
38

class-explorer

Find the list of all your PHP classes and more.
PHP
9
star
39

drupal

This Composer package is an installer that will download Drupal from the http://drupal.org website and unpack it at the root of your Composer project.
9
star
40

print.service

PDF, docx, html generator service of docx or twig template
PHP
8
star
41

map-optimizer

A tool to automatically optimize a Tiled map for usage in Phaser 3
JavaScript
8
star
42

funky

Write service providers easily using annotations
PHP
7
star
43

csrf-header-check-middleware

A PHP PSR-15 (http-interop) compliant middleware that defends your application against CSRF attacks.
PHP
7
star
44

interop.silex.di

This project is a very simple extension to the Silex microframework. It adds to Silex the capability to use any DI container (not only Pimple).
PHP
7
star
45

tdbm-bundle

A Symfony bundle for TDBM.
PHP
6
star
46

schema-analyzer

A package that offers utility tools to analyze database schemas (on top of Doctrine DBAL)
PHP
6
star
47

utils.session.optimistic-session-handler

Session handler that releases session lock quickly. Usefull for multiple ajax calls on the same page
PHP
6
star
48

metahydrator

A configurable implementation of mouf's Hydrator interface
PHP
6
star
49

workadventure-map-forumphp

A WorkAdventure map for AFUP's ForumPHP 2020 event
HTML
5
star
50

crystal-project

This package contains the everaldo icon set. This is a set of icons that can be used in any web application.
5
star
51

splash-router

A PSR-15 compliant router using annotations
PHP
5
star
52

graphqlite-symfony-validator-bridge

Adds support for Symfony Validator in GraphQLite
PHP
5
star
53

alias-container

This package contains a really minimalist dependency injection container that can be used to create aliases of instances in existing containers.
PHP
5
star
54

docker-images-mysql

MySQL container with top-notch developer experience
Shell
4
star
55

workadventure-php-community-map

A map for the PHP community on WorkAdventure
JavaScript
4
star
56

service-provider-bridge-bundle

This Symfony Bundle enables Symfony applications to use service providers as defined in container-interop/service-provider
PHP
4
star
57

rnb-toolbox

Toolbox to create amazing plugins for our react-native boilerplate. 🧰
TypeScript
3
star
58

utils.common.conditioninterface

This package contains one interface for condition, and a few classes that implement it. A condition is a class that possesses an "isOk" method. The condition returns true if the condition is met, and false otherwise.
PHP
3
star
59

fluid-hydrator

PHP
3
star
60

DBFaker

Easy test data in your database !
PHP
3
star
61

gitlab-hook-middleware

A PSR-15 middleware to handle Gitlab hooks
PHP
3
star
62

archive-installer

This is a simple installer that let's you create simple Composer packages that are actually downloading and extracting an archive from the web.
PHP
3
star
63

laravel-universal-service-provider

This bridge allows Laravel applications to use service providers as defined in container-interop/service-provider
PHP
3
star
64

tdbm-laravel

A Laravel service provider package to help you get started with TDBM in Laravel
PHP
3
star
65

middleware-list-universal-module

Cross-framework module providing a service containing a list of middlewares
PHP
3
star
66

prefixer-container

This package contains a really minimalist dependency injection container that acts as a proxy in front of a target container. Its goal is to prefix all instances names in the target container.
PHP
3
star
67

swift-twig-mail-template

This package contains a utility class to render Swift mail messages using Twig for templating
PHP
3
star
68

database.doctrine-orm-wrapper

This package contains wrapper classes that make Doctrine ORM easy to use in Mouf
PHP
3
star
69

mvc.bce

BCE is made to make your live easy. It will help you in building forms very quickly, handles form rendering, both client and server-side validation, and persistance.
PHP
3
star
70

mvc.splash-common

The Core part of Splash (an MVC framework). It is used by Splash itself, but also by Drusplash (the Splash wrapper for Drupal)
PHP
3
star
71

mvc.splash

A MVC framework deeply integrated with Mouf
PHP
2
star
72

kickoff-docker-php-images

Base images of kickoff-docker-php
Roff
2
star
73

gitlab_scrutinizer_hook_adapter

This project is an adapter between Gitlab web hooks and Scrutinizer post-receive hook triggers
PHP
2
star
74

tom-cli

A dedicated CLI for TheCodingMachine React-Native Boilerplate !
JavaScript
2
star
75

graphqlite-universal-service-provider

Cross-framework module for GraphQLite using container-interop/service-provider
PHP
2
star
76

gitlab-registry-api

Library to use the Gitlab registry api in php
PHP
2
star
77

easy-entity-reader

This Drupal 8 module helps developers access entity content.
PHP
2
star
78

tdbm-graphql

A class generator that will generate GraphQL types from your database schema (using thecodingmachine/graphqlite)
PHP
2
star
79

k8s-gitlabci

PHP
2
star
80

utils.log.psr.multi-logger

This package contains a PSR-3 compatible logger that wrap a set of loggers
PHP
2
star
81

cache-utils

Store file related cache items easily
PHP
2
star
82

tdbm-graphql-bundle

A Symfony bundle for thecodingmachine/tdbm-graphql.
PHP
2
star
83

jquery.tcm.monthpicker

The jQuery TCM Monthpicker is a highly configurable plugin that adds monthpicker functionality to your pages. You can customize the date format and language, restrict the selectable date ranges and add in buttons and other navigation options easily.
2
star
84

html.tags

This package contains a pure PHP object representation of HTML5 tags. There is one class for each existing HTML tag, and one getter/setter per attribute.
PHP
2
star
85

integration.joomla.moufla-joomlaplugin

This is the plugin that integrate Mouf in a Joomla environment. There are two other repositories that are linked to this one.
PHP
1
star
86

lazy-array

This package provides an array than can lazily instantiate the objects it contains.
PHP
1
star
87

service-provider-utils

This package contains a set of tools to work with container-interop's service-providers.
PHP
1
star
88

common-factories

This project provides utility factories that can be used directly in service providers complying with the container-interop/service-provider standard.
PHP
1
star
89

container-discovery

Allowing discovery of container objects through Puli
PHP
1
star
90

quiz-demo-joomla

PHP
1
star
91

drupal-stratigility-bridge

This Drupal 8 module provides a bridge to include PSR-15 middlewares through Stratigility.
PHP
1
star
92

tdbm-hydrator

A PHP hydrator allowing easy mapping between an array and an object.
PHP
1
star
93

yaml-definition-loader

Provides a loader that can convert YAML files to container definitions compatible with the definition-interop standard.
PHP
1
star
94

security.daos.tdbm

This package contains a basic user/role/right database model for TDBM.
PHP
1
star
95

html.widgets.fileuploaderwidget

This package contains an upload widget based on File Uploader plugin. This allows easy uploading of files in AJAX or HTML5.
PHP
1
star
96

utils.graphics.mouf-imagine

Wrapper around the Imagine library, that allows to associate a set of Imagine Filters to an URL, like the LiipImagineBundle does for Symfony
PHP
1
star
97

forumphp2016demo

The PHP demo made for Paris Forum PHP 2016
PHP
1
star
98

utils.graphics.mouf-image

Images handler interface for resizing, croping, or any other action
PHP
1
star
99

html.html_element

This package contains the HtmlElementInterface interface that can be used to output HTML on a page. It also features base classes implementing this interface.
PHP
1
star
100

interop.symfony.di

This package contains an implementation of the Symfony 2 DI container that can be extended using other DI containers (from other frameworks).
PHP
1
star