From 236f8a776420f3a45d73cdc662b9733ecd31d0df Mon Sep 17 00:00:00 2001
From: le0m
Date: Fri, 13 Dec 2024 15:51:41 +0100
Subject: [PATCH] feat: chialab/php-compat images
---
.github/workflows/compat.yml | 93 ++++++++++
compat/Dockerfile.5.6 | 260 ++++++++++++++++++++++++++++
compat/Dockerfile.5.6-apache | 325 +++++++++++++++++++++++++++++++++++
compat/Dockerfile.5.6-fpm | 300 ++++++++++++++++++++++++++++++++
compat/Makefile | 85 +++++++++
compat/README.md | 82 +++++++++
dev/README.md | 2 +-
pcov/README.md | 2 +-
xhprof/README.md | 2 +-
9 files changed, 1148 insertions(+), 3 deletions(-)
create mode 100644 .github/workflows/compat.yml
create mode 100644 compat/Dockerfile.5.6
create mode 100644 compat/Dockerfile.5.6-apache
create mode 100644 compat/Dockerfile.5.6-fpm
create mode 100644 compat/Makefile
create mode 100644 compat/README.md
diff --git a/.github/workflows/compat.yml b/.github/workflows/compat.yml
new file mode 100644
index 0000000..e1a6379
--- /dev/null
+++ b/.github/workflows/compat.yml
@@ -0,0 +1,93 @@
+name: Build, test and publish compatibility images
+
+on:
+ schedule:
+ # chosen by fair dice roll
+ - cron: '42 18 * * 3'
+ push:
+ branches:
+ - main
+ pull_request:
+ types: [opened, synchronize]
+
+jobs:
+ test:
+ name: Build and test images
+ runs-on: ubuntu-latest
+ if: ${{ !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
+ strategy:
+ matrix:
+ version: [ '5.6' ]
+ flavor: [ '', '-apache', '-fpm' ]
+ services:
+ registry:
+ image: registry:2
+ ports:
+ - 5000:5000
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Build image for testing
+ uses: docker/build-push-action@v5
+ with:
+ cache-from: type=registry,ref=chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }}
+ cache-to: type=inline
+ context: ./compat
+ file: ${{ format('compat/{0}.{1}{2}', 'Dockerfile', matrix.version, matrix.flavor) }}
+ tags: localhost:5000/chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }}
+ push: true
+
+ - name: Test image
+ env:
+ REGISTRY: localhost:5000/
+ VERSION: ${{ matrix.version }}${{ matrix.flavor }}
+ run: 'docker pull localhost:5000/chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }} && make -C compat test'
+
+ publish:
+ name: Build and publish multi-architecture images
+ runs-on: ubuntu-latest
+ needs: test
+ if: ${{ github.event_name != 'pull_request' && !contains(github.event.commits[0].message, '[skip ci]') && !contains(github.event.commits[0].message, '[ci skip]') }}
+ strategy:
+ matrix:
+ version: [ '5.6' ]
+ flavor: [ '', '-apache', '-fpm' ]
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up QEMU
+ run: |
+ docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ with:
+ driver-opts: network=host
+
+ - name: Login to DockerHub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build image and push to registry
+ uses: docker/build-push-action@v5
+ with:
+ platforms: linux/amd64,linux/arm64
+ cache-from: type=registry,ref=chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }}
+ cache-to: type=inline
+ context: ./compat
+ file: ${{ format('compat/{0}.{1}{2}', 'Dockerfile', matrix.version, matrix.flavor) }}
+ tags: |
+ chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }}
+ ghcr.io/chialab/php-compat:${{ matrix.version }}${{ matrix.flavor }}
+ push: true
diff --git a/compat/Dockerfile.5.6 b/compat/Dockerfile.5.6
new file mode 100644
index 0000000..c5f5d0d
--- /dev/null
+++ b/compat/Dockerfile.5.6
@@ -0,0 +1,260 @@
+#
+# This is taken from the official PHP image's Dockerfile (https://github.com/docker-library/php/tree/783878384a8f3953ed571e5a34ba0fe546726c85)
+# and slightly fixed to work in this day and age.
+#
+
+FROM debian:stretch-slim
+
+LABEL maintainer="dev@chialab.io"
+
+# Fix Debian 9 (Stretch) source list, because it has been moved to archive, and update packages.
+RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
+ -e 's/security.debian.org/archive.debian.org/g' \
+ -e '/stretch-updates/d' /etc/apt/sources.list \
+ && apt-get update && apt-get upgrade -y
+
+# prevent Debian's PHP packages from being installed
+# https://github.com/docker-library/php/pull/542
+RUN set -eux; \
+ { \
+ echo 'Package: php*'; \
+ echo 'Pin: release *'; \
+ echo 'Pin-Priority: -1'; \
+ } > /etc/apt/preferences.d/no-debian-php
+
+# dependencies required for running "phpize"
+# (see persistent deps below)
+ENV PHPIZE_DEPS \
+ autoconf \
+ dpkg-dev \
+ file \
+ g++ \
+ gcc \
+ libc-dev \
+ make \
+ pkg-config \
+ re2c
+
+# persistent / runtime deps
+RUN apt-get update && apt-get install -y \
+ $PHPIZE_DEPS \
+ ca-certificates \
+ curl \
+ xz-utils \
+ --no-install-recommends && rm -r /var/lib/apt/lists/*
+
+ENV PHP_INI_DIR /usr/local/etc/php
+RUN mkdir -p $PHP_INI_DIR/conf.d
+
+####
+####
+
+# Apply stack smash protection to functions using local buffers and alloca()
+# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
+# Enable optimization (-O2)
+# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
+# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
+# https://github.com/docker-library/php/issues/272
+ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
+ENV PHP_CPPFLAGS="$PHP_CFLAGS"
+ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
+
+ENV GPG_KEYS 0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
+
+ENV PHP_VERSION 5.6.40
+ENV PHP_URL="https://secure.php.net/get/php-5.6.40.tar.xz/from/this/mirror" PHP_ASC_URL="https://secure.php.net/get/php-5.6.40.tar.xz.asc/from/this/mirror"
+ENV PHP_SHA256="1369a51eee3995d7fbd1c5342e5cc917760e276d561595b6052b21ace2656d1c" PHP_MD5=""
+
+RUN set -xe; \
+ \
+ fetchDeps=' \
+ wget \
+ '; \
+ if ! command -v gpg > /dev/null; then \
+ fetchDeps="$fetchDeps \
+ dirmngr \
+ gnupg \
+ "; \
+ fi; \
+ apt-get update; \
+ apt-get install -y --no-install-recommends $fetchDeps; \
+ rm -rf /var/lib/apt/lists/*; \
+ \
+ mkdir -p /usr/src; \
+ cd /usr/src; \
+ \
+ wget -O php.tar.xz "$PHP_URL"; \
+ \
+ if [ -n "$PHP_SHA256" ]; then \
+ echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
+ fi; \
+ if [ -n "$PHP_MD5" ]; then \
+ echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
+ fi; \
+ \
+ if [ -n "$PHP_ASC_URL" ]; then \
+ wget -O php.tar.xz.asc "$PHP_ASC_URL"; \
+ export GNUPGHOME="$(mktemp -d)"; \
+ for key in $GPG_KEYS; do \
+ gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
+ done; \
+ gpg --batch --verify php.tar.xz.asc php.tar.xz; \
+ command -v gpgconf > /dev/null && gpgconf --kill all; \
+ rm -rf "$GNUPGHOME"; \
+ fi; \
+ \
+ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps
+
+COPY --from=php:5.6 /usr/local/bin/docker-php-source /usr/local/bin/
+
+RUN set -eux; \
+ \
+ savedAptMark="$(apt-mark showmanual)"; \
+ apt-get update; \
+ apt-get install -y --no-install-recommends \
+ libcurl4-openssl-dev \
+ libedit-dev \
+ libsqlite3-dev \
+ libssl1.0-dev \
+ libxml2-dev \
+ zlib1g-dev \
+ libmariadb2 libmariadbclient-dev-compat \
+ ${PHP_EXTRA_BUILD_DEPS:-} \
+ ; \
+ rm -rf /var/lib/apt/lists/*; \
+ \
+ export \
+ CFLAGS="$PHP_CFLAGS" \
+ CPPFLAGS="$PHP_CPPFLAGS" \
+ LDFLAGS="$PHP_LDFLAGS" \
+ ; \
+ docker-php-source extract; \
+ cd /usr/src/php; \
+ gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
+ debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
+# https://bugs.php.net/bug.php?id=74125
+ if [ ! -d /usr/include/curl ]; then \
+ ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
+ fi; \
+ ./configure \
+ --build="$gnuArch" \
+ --with-config-file-path="$PHP_INI_DIR" \
+ --with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
+ \
+# make sure invalid --configure-flags are fatal errors intead of just warnings
+ --enable-option-checking=fatal \
+ \
+# https://github.com/docker-library/php/issues/439
+ --with-mhash \
+ \
+# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
+ --enable-ftp \
+# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
+ --enable-mbstring \
+# Use MariaDB's libmysqlclient library instead of mysqlnd to be able to communicate with MySQL 8+, which uses new locales of the utf8mb4 family that are unknown to old mysqlnd
+ --disable-mysqlnd \
+ --with-mysql="/usr" \
+ --with-mysqli="/usr/bin/mysql_config" \
+ --with-pdo-mysql="/usr" \
+ \
+ --with-curl \
+ --with-libedit \
+ --with-openssl \
+ --with-zlib \
+ \
+# bundled pcre does not support JIT on s390x
+# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
+ $(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
+ --with-libdir="lib/$debMultiarch" \
+ \
+ ${PHP_EXTRA_CONFIGURE_ARGS:-} \
+ ; \
+ make -j "$(nproc)"; \
+ make install; \
+ find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
+ make clean; \
+ \
+# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
+ cp -v php.ini-* "$PHP_INI_DIR/"; \
+ \
+ cd /; \
+ docker-php-source delete; \
+ \
+# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
+ apt-mark auto '.*' > /dev/null; \
+ [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
+ find /usr/local -type f -executable -exec ldd '{}' ';' \
+ | awk '/=>/ { print $(NF-1) }' \
+ | sort -u \
+ | xargs -r dpkg-query --search \
+ | cut -d: -f1 \
+ | sort -u \
+ | xargs -r apt-mark manual \
+ ; \
+ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
+ \
+ php --version; \
+ \
+# https://github.com/docker-library/php/issues/443
+ pecl update-channels; \
+ rm -rf /tmp/pear ~/.pearrc
+
+COPY --from=php:5.6 /usr/local/bin/docker-php-ext-* /usr/local/bin/docker-php-entrypoint /usr/local/bin/
+
+ENTRYPOINT ["docker-php-entrypoint"]
+####
+CMD ["php", "-a"]
+####
+
+# Download script to install PHP extensions and dependencies
+ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
+
+RUN chmod +x /usr/local/bin/install-php-extensions
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get update -q \
+ && DEBIAN_FRONTEND=noninteractive apt-get install -qq -y \
+ curl \
+ git \
+ zip unzip \
+# iconv, mbstring and pdo_sqlite are omitted as they are already installed
+ && PHP_EXTENSIONS=" \
+ amqp \
+ bcmath \
+ bz2 \
+ calendar \
+ event \
+ exif \
+ gd \
+ gettext \
+ imagick \
+ intl \
+ ldap \
+ mcrypt \
+ memcached \
+ mysql \
+ mysqli \
+ opcache \
+ pdo_mysql \
+ pdo_pgsql \
+ pgsql \
+ redis \
+ soap \
+ sockets \
+ xsl \
+ zip \
+ " \
+ && install-php-extensions $PHP_EXTENSIONS
+
+# Install Composer.
+ENV PATH=$PATH:/root/composer/vendor/bin \
+ COMPOSER_ALLOW_SUPERUSER=1 \
+ COMPOSER_HOME=/root/composer
+RUN cd /opt \
+ # Download installer and check for its integrity.
+ && curl -sSL https://getcomposer.org/installer > composer-setup.php \
+ && curl -sSL https://composer.github.io/installer.sha384sum > composer-setup.sha384sum \
+ && sha384sum --check composer-setup.sha384sum \
+ # Install Composer 2.
+ && php composer-setup.php --install-dir=/usr/local/bin --filename=composer --2 \
+ # Remove installer files.
+ && rm /opt/composer-setup.php /opt/composer-setup.sha384sum
diff --git a/compat/Dockerfile.5.6-apache b/compat/Dockerfile.5.6-apache
new file mode 100644
index 0000000..ba8be70
--- /dev/null
+++ b/compat/Dockerfile.5.6-apache
@@ -0,0 +1,325 @@
+#
+# This is taken from the official PHP image's Dockerfile (https://github.com/docker-library/php/tree/783878384a8f3953ed571e5a34ba0fe546726c85)
+# and slightly fixed to work in this day and age.
+#
+
+FROM debian:stretch-slim
+
+LABEL maintainer="dev@chialab.io"
+
+# Fix Debian 9 (Stretch) source list, because it has been moved to archive, and update packages.
+RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
+ -e 's/security.debian.org/archive.debian.org/g' \
+ -e '/stretch-updates/d' /etc/apt/sources.list \
+ && apt-get update && apt-get upgrade -y
+
+# prevent Debian's PHP packages from being installed
+# https://github.com/docker-library/php/pull/542
+RUN set -eux; \
+ { \
+ echo 'Package: php*'; \
+ echo 'Pin: release *'; \
+ echo 'Pin-Priority: -1'; \
+ } > /etc/apt/preferences.d/no-debian-php
+
+# dependencies required for running "phpize"
+# (see persistent deps below)
+ENV PHPIZE_DEPS \
+ autoconf \
+ dpkg-dev \
+ file \
+ g++ \
+ gcc \
+ libc-dev \
+ make \
+ pkg-config \
+ re2c
+
+# persistent / runtime deps
+RUN apt-get update && apt-get install -y \
+ $PHPIZE_DEPS \
+ ca-certificates \
+ curl \
+ xz-utils \
+ --no-install-recommends && rm -r /var/lib/apt/lists/*
+
+ENV PHP_INI_DIR /usr/local/etc/php
+RUN mkdir -p $PHP_INI_DIR/conf.d
+
+####
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ apache2 \
+ && rm -rf /var/lib/apt/lists/*
+
+ENV APACHE_CONFDIR /etc/apache2
+ENV APACHE_ENVVARS $APACHE_CONFDIR/envvars
+
+RUN set -eux; \
+ \
+# generically convert lines like
+# export APACHE_RUN_USER=www-data
+# into
+# : ${APACHE_RUN_USER:=www-data}
+# export APACHE_RUN_USER
+# so that they can be overridden at runtime ("-e APACHE_RUN_USER=...")
+ sed -ri 's/^export ([^=]+)=(.*)$/: ${\1:=\2}\nexport \1/' "$APACHE_ENVVARS"; \
+ \
+# setup directories and permissions
+ . "$APACHE_ENVVARS"; \
+ for dir in \
+ "$APACHE_LOCK_DIR" \
+ "$APACHE_RUN_DIR" \
+ "$APACHE_LOG_DIR" \
+ /var/www/html \
+ ; do \
+ rm -rvf "$dir"; \
+ mkdir -p "$dir"; \
+ chown "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$dir"; \
+# allow running as an arbitrary user (https://github.com/docker-library/php/issues/743)
+ chmod 777 "$dir"; \
+ done; \
+ \
+# logs should go to stdout / stderr
+ ln -sfT /dev/stderr "$APACHE_LOG_DIR/error.log"; \
+ ln -sfT /dev/stdout "$APACHE_LOG_DIR/access.log"; \
+ ln -sfT /dev/stdout "$APACHE_LOG_DIR/other_vhosts_access.log"; \
+ chown -R --no-dereference "$APACHE_RUN_USER:$APACHE_RUN_GROUP" "$APACHE_LOG_DIR"
+
+# Apache + PHP requires preforking Apache for best results
+RUN a2dismod mpm_event && a2enmod mpm_prefork
+
+# PHP files should be handled by PHP, and should be preferred over any other file type
+RUN { \
+ echo ''; \
+ echo '\tSetHandler application/x-httpd-php'; \
+ echo ''; \
+ echo; \
+ echo 'DirectoryIndex disabled'; \
+ echo 'DirectoryIndex index.php index.html'; \
+ echo; \
+ echo ''; \
+ echo '\tOptions -Indexes'; \
+ echo '\tAllowOverride All'; \
+ echo ''; \
+ } | tee "$APACHE_CONFDIR/conf-available/docker-php.conf" \
+ && a2enconf docker-php
+
+ENV PHP_EXTRA_BUILD_DEPS apache2-dev
+ENV PHP_EXTRA_CONFIGURE_ARGS --with-apxs2 --disable-cgi
+####
+
+# Apply stack smash protection to functions using local buffers and alloca()
+# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
+# Enable optimization (-O2)
+# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
+# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
+# https://github.com/docker-library/php/issues/272
+ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
+ENV PHP_CPPFLAGS="$PHP_CFLAGS"
+ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
+
+ENV GPG_KEYS 0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
+
+ENV PHP_VERSION 5.6.40
+ENV PHP_URL="https://secure.php.net/get/php-5.6.40.tar.xz/from/this/mirror" PHP_ASC_URL="https://secure.php.net/get/php-5.6.40.tar.xz.asc/from/this/mirror"
+ENV PHP_SHA256="1369a51eee3995d7fbd1c5342e5cc917760e276d561595b6052b21ace2656d1c" PHP_MD5=""
+
+RUN set -xe; \
+ \
+ fetchDeps=' \
+ wget \
+ '; \
+ if ! command -v gpg > /dev/null; then \
+ fetchDeps="$fetchDeps \
+ dirmngr \
+ gnupg \
+ "; \
+ fi; \
+ apt-get update; \
+ apt-get install -y --no-install-recommends $fetchDeps; \
+ rm -rf /var/lib/apt/lists/*; \
+ \
+ mkdir -p /usr/src; \
+ cd /usr/src; \
+ \
+ wget -O php.tar.xz "$PHP_URL"; \
+ \
+ if [ -n "$PHP_SHA256" ]; then \
+ echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
+ fi; \
+ if [ -n "$PHP_MD5" ]; then \
+ echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
+ fi; \
+ \
+ if [ -n "$PHP_ASC_URL" ]; then \
+ wget -O php.tar.xz.asc "$PHP_ASC_URL"; \
+ export GNUPGHOME="$(mktemp -d)"; \
+ for key in $GPG_KEYS; do \
+ gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
+ done; \
+ gpg --batch --verify php.tar.xz.asc php.tar.xz; \
+ command -v gpgconf > /dev/null && gpgconf --kill all; \
+ rm -rf "$GNUPGHOME"; \
+ fi; \
+ \
+ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps
+
+COPY --from=php:5.6-apache /usr/local/bin/docker-php-source /usr/local/bin/
+
+RUN set -eux; \
+ \
+ savedAptMark="$(apt-mark showmanual)"; \
+ apt-get update; \
+ apt-get install -y --no-install-recommends \
+ libcurl4-openssl-dev \
+ libedit-dev \
+ libsqlite3-dev \
+ libssl1.0-dev \
+ libxml2-dev \
+ zlib1g-dev \
+ libmariadb2 libmariadbclient-dev-compat \
+ ${PHP_EXTRA_BUILD_DEPS:-} \
+ ; \
+ rm -rf /var/lib/apt/lists/*; \
+ \
+ export \
+ CFLAGS="$PHP_CFLAGS" \
+ CPPFLAGS="$PHP_CPPFLAGS" \
+ LDFLAGS="$PHP_LDFLAGS" \
+ ; \
+ docker-php-source extract; \
+ cd /usr/src/php; \
+ gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
+ debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
+# https://bugs.php.net/bug.php?id=74125
+ if [ ! -d /usr/include/curl ]; then \
+ ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
+ fi; \
+ ./configure \
+ --build="$gnuArch" \
+ --with-config-file-path="$PHP_INI_DIR" \
+ --with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
+ \
+# make sure invalid --configure-flags are fatal errors intead of just warnings
+ --enable-option-checking=fatal \
+ \
+# https://github.com/docker-library/php/issues/439
+ --with-mhash \
+ \
+# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
+ --enable-ftp \
+# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
+ --enable-mbstring \
+# Use MariaDB's libmysqlclient library instead of mysqlnd to be able to communicate with MySQL 8+, which uses new locales of the utf8mb4 family that are unknown to old mysqlnd
+ --disable-mysqlnd \
+ --with-mysql="/usr" \
+ --with-mysqli="/usr/bin/mysql_config" \
+ --with-pdo-mysql="/usr" \
+ \
+ --with-curl \
+ --with-libedit \
+ --with-openssl \
+ --with-zlib \
+ \
+# bundled pcre does not support JIT on s390x
+# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
+ $(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
+ --with-libdir="lib/$debMultiarch" \
+ \
+ ${PHP_EXTRA_CONFIGURE_ARGS:-} \
+ ; \
+ make -j "$(nproc)"; \
+ make install; \
+ find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
+ make clean; \
+ \
+# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
+ cp -v php.ini-* "$PHP_INI_DIR/"; \
+ \
+ cd /; \
+ docker-php-source delete; \
+ \
+# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
+ apt-mark auto '.*' > /dev/null; \
+ [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
+ find /usr/local -type f -executable -exec ldd '{}' ';' \
+ | awk '/=>/ { print $(NF-1) }' \
+ | sort -u \
+ | xargs -r dpkg-query --search \
+ | cut -d: -f1 \
+ | sort -u \
+ | xargs -r apt-mark manual \
+ ; \
+ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
+ \
+ php --version; \
+ \
+# https://github.com/docker-library/php/issues/443
+ pecl update-channels; \
+ rm -rf /tmp/pear ~/.pearrc
+
+COPY --from=php:5.6-apache /usr/local/bin/docker-php-ext-* /usr/local/bin/docker-php-entrypoint /usr/local/bin/
+
+ENTRYPOINT ["docker-php-entrypoint"]
+####
+COPY --from=php:5.6-apache /usr/local/bin/apache2-foreground /usr/local/bin/
+WORKDIR /var/www/html
+
+EXPOSE 80
+CMD ["apache2-foreground"]
+####
+
+# Download script to install PHP extensions and dependencies
+ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
+
+RUN chmod +x /usr/local/bin/install-php-extensions
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get update -q \
+ && DEBIAN_FRONTEND=noninteractive apt-get install -qq -y \
+ curl \
+ git \
+ zip unzip \
+# iconv, mbstring and pdo_sqlite are omitted as they are already installed
+ && PHP_EXTENSIONS=" \
+ amqp \
+ bcmath \
+ bz2 \
+ calendar \
+ event \
+ exif \
+ gd \
+ gettext \
+ imagick \
+ intl \
+ ldap \
+ mcrypt \
+ memcached \
+ mysql \
+ mysqli \
+ opcache \
+ pdo_mysql \
+ pdo_pgsql \
+ pgsql \
+ redis \
+ soap \
+ sockets \
+ xsl \
+ zip \
+ " \
+ && install-php-extensions $PHP_EXTENSIONS \
+ && if command -v a2enmod; then a2enmod rewrite; fi
+
+# Install Composer.
+ENV PATH=$PATH:/root/composer/vendor/bin \
+ COMPOSER_ALLOW_SUPERUSER=1 \
+ COMPOSER_HOME=/root/composer
+RUN cd /opt \
+ # Download installer and check for its integrity.
+ && curl -sSL https://getcomposer.org/installer > composer-setup.php \
+ && curl -sSL https://composer.github.io/installer.sha384sum > composer-setup.sha384sum \
+ && sha384sum --check composer-setup.sha384sum \
+ # Install Composer 2.
+ && php composer-setup.php --install-dir=/usr/local/bin --filename=composer --2 \
+ # Remove installer files.
+ && rm /opt/composer-setup.php /opt/composer-setup.sha384sum
diff --git a/compat/Dockerfile.5.6-fpm b/compat/Dockerfile.5.6-fpm
new file mode 100644
index 0000000..ee8bd8f
--- /dev/null
+++ b/compat/Dockerfile.5.6-fpm
@@ -0,0 +1,300 @@
+#
+# This is taken from the official PHP image's Dockerfile (https://github.com/docker-library/php/tree/783878384a8f3953ed571e5a34ba0fe546726c85)
+# and slightly fixed to work in this day and age.
+#
+
+FROM debian:stretch-slim
+
+LABEL maintainer="dev@chialab.io"
+
+# Fix Debian 9 (Stretch) source list, because it has been moved to archive, and update packages.
+RUN sed -i -e 's/deb.debian.org/archive.debian.org/g' \
+ -e 's/security.debian.org/archive.debian.org/g' \
+ -e '/stretch-updates/d' /etc/apt/sources.list \
+ && apt-get update && apt-get upgrade -y
+
+# prevent Debian's PHP packages from being installed
+# https://github.com/docker-library/php/pull/542
+RUN set -eux; \
+ { \
+ echo 'Package: php*'; \
+ echo 'Pin: release *'; \
+ echo 'Pin-Priority: -1'; \
+ } > /etc/apt/preferences.d/no-debian-php
+
+# dependencies required for running "phpize"
+# (see persistent deps below)
+ENV PHPIZE_DEPS \
+ autoconf \
+ dpkg-dev \
+ file \
+ g++ \
+ gcc \
+ libc-dev \
+ make \
+ pkg-config \
+ re2c
+
+# persistent / runtime deps
+RUN apt-get update && apt-get install -y \
+ $PHPIZE_DEPS \
+ ca-certificates \
+ curl \
+ xz-utils \
+ --no-install-recommends && rm -r /var/lib/apt/lists/*
+
+ENV PHP_INI_DIR /usr/local/etc/php
+RUN mkdir -p $PHP_INI_DIR/conf.d
+
+####
+ENV PHP_EXTRA_CONFIGURE_ARGS --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data --disable-cgi
+####
+
+# Apply stack smash protection to functions using local buffers and alloca()
+# Make PHP's main executable position-independent (improves ASLR security mechanism, and has no performance impact on x86_64)
+# Enable optimization (-O2)
+# Enable linker optimization (this sorts the hash buckets to improve cache locality, and is non-default)
+# Adds GNU HASH segments to generated executables (this is used if present, and is much faster than sysv hash; in this configuration, sysv hash is also generated)
+# https://github.com/docker-library/php/issues/272
+ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2"
+ENV PHP_CPPFLAGS="$PHP_CFLAGS"
+ENV PHP_LDFLAGS="-Wl,-O1 -Wl,--hash-style=both -pie"
+
+ENV GPG_KEYS 0BD78B5F97500D450838F95DFE857D9A90D90EC1 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
+
+ENV PHP_VERSION 5.6.40
+ENV PHP_URL="https://secure.php.net/get/php-5.6.40.tar.xz/from/this/mirror" PHP_ASC_URL="https://secure.php.net/get/php-5.6.40.tar.xz.asc/from/this/mirror"
+ENV PHP_SHA256="1369a51eee3995d7fbd1c5342e5cc917760e276d561595b6052b21ace2656d1c" PHP_MD5=""
+
+RUN set -xe; \
+ \
+ fetchDeps=' \
+ wget \
+ '; \
+ if ! command -v gpg > /dev/null; then \
+ fetchDeps="$fetchDeps \
+ dirmngr \
+ gnupg \
+ "; \
+ fi; \
+ apt-get update; \
+ apt-get install -y --no-install-recommends $fetchDeps; \
+ rm -rf /var/lib/apt/lists/*; \
+ \
+ mkdir -p /usr/src; \
+ cd /usr/src; \
+ \
+ wget -O php.tar.xz "$PHP_URL"; \
+ \
+ if [ -n "$PHP_SHA256" ]; then \
+ echo "$PHP_SHA256 *php.tar.xz" | sha256sum -c -; \
+ fi; \
+ if [ -n "$PHP_MD5" ]; then \
+ echo "$PHP_MD5 *php.tar.xz" | md5sum -c -; \
+ fi; \
+ \
+ if [ -n "$PHP_ASC_URL" ]; then \
+ wget -O php.tar.xz.asc "$PHP_ASC_URL"; \
+ export GNUPGHOME="$(mktemp -d)"; \
+ for key in $GPG_KEYS; do \
+ gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \
+ done; \
+ gpg --batch --verify php.tar.xz.asc php.tar.xz; \
+ command -v gpgconf > /dev/null && gpgconf --kill all; \
+ rm -rf "$GNUPGHOME"; \
+ fi; \
+ \
+ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $fetchDeps
+
+COPY --from=php:5.6-fpm /usr/local/bin/docker-php-source /usr/local/bin/
+
+RUN set -eux; \
+ \
+ savedAptMark="$(apt-mark showmanual)"; \
+ apt-get update; \
+ apt-get install -y --no-install-recommends \
+ libcurl4-openssl-dev \
+ libedit-dev \
+ libsqlite3-dev \
+ libssl1.0-dev \
+ libxml2-dev \
+ zlib1g-dev \
+ libmariadb2 libmariadbclient-dev-compat \
+ ${PHP_EXTRA_BUILD_DEPS:-} \
+ ; \
+ rm -rf /var/lib/apt/lists/*; \
+ \
+ export \
+ CFLAGS="$PHP_CFLAGS" \
+ CPPFLAGS="$PHP_CPPFLAGS" \
+ LDFLAGS="$PHP_LDFLAGS" \
+ ; \
+ docker-php-source extract; \
+ cd /usr/src/php; \
+ gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
+ debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \
+# https://bugs.php.net/bug.php?id=74125
+ if [ ! -d /usr/include/curl ]; then \
+ ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl; \
+ fi; \
+ ./configure \
+ --build="$gnuArch" \
+ --with-config-file-path="$PHP_INI_DIR" \
+ --with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
+ \
+# make sure invalid --configure-flags are fatal errors intead of just warnings
+ --enable-option-checking=fatal \
+ \
+# https://github.com/docker-library/php/issues/439
+ --with-mhash \
+ \
+# --enable-ftp is included here because ftp_ssl_connect() needs ftp to be compiled statically (see https://github.com/docker-library/php/issues/236)
+ --enable-ftp \
+# --enable-mbstring is included here because otherwise there's no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
+ --enable-mbstring \
+# Use MariaDB's libmysqlclient library instead of mysqlnd to be able to communicate with MySQL 8+, which uses new locales of the utf8mb4 family that are unknown to old mysqlnd
+ --disable-mysqlnd \
+ --with-mysql="/usr" \
+ --with-mysqli="/usr/bin/mysql_config" \
+ --with-pdo-mysql="/usr" \
+ \
+ --with-curl \
+ --with-libedit \
+ --with-openssl \
+ --with-zlib \
+ \
+# bundled pcre does not support JIT on s390x
+# https://manpages.debian.org/stretch/libpcre3-dev/pcrejit.3.en.html#AVAILABILITY_OF_JIT_SUPPORT
+ $(test "$gnuArch" = 's390x-linux-gnu' && echo '--without-pcre-jit') \
+ --with-libdir="lib/$debMultiarch" \
+ \
+ ${PHP_EXTRA_CONFIGURE_ARGS:-} \
+ ; \
+ make -j "$(nproc)"; \
+ make install; \
+ find /usr/local/bin /usr/local/sbin -type f -executable -exec strip --strip-all '{}' + || true; \
+ make clean; \
+ \
+# https://github.com/docker-library/php/issues/692 (copy default example "php.ini" files somewhere easily discoverable)
+ cp -v php.ini-* "$PHP_INI_DIR/"; \
+ \
+ cd /; \
+ docker-php-source delete; \
+ \
+# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
+ apt-mark auto '.*' > /dev/null; \
+ [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
+ find /usr/local -type f -executable -exec ldd '{}' ';' \
+ | awk '/=>/ { print $(NF-1) }' \
+ | sort -u \
+ | xargs -r dpkg-query --search \
+ | cut -d: -f1 \
+ | sort -u \
+ | xargs -r apt-mark manual \
+ ; \
+ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
+ \
+ php --version; \
+ \
+# https://github.com/docker-library/php/issues/443
+ pecl update-channels; \
+ rm -rf /tmp/pear ~/.pearrc
+
+COPY --from=php:5.6-fpm /usr/local/bin/docker-php-ext-* /usr/local/bin/docker-php-entrypoint /usr/local/bin/
+
+ENTRYPOINT ["docker-php-entrypoint"]
+####
+WORKDIR /var/www/html
+
+RUN set -ex \
+ && cd /usr/local/etc \
+ && if [ -d php-fpm.d ]; then \
+ # for some reason, upstream's php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
+ sed 's!=NONE/!=!g' php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
+ cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
+ else \
+ # PHP 5.x doesn't use "include=" by default, so we'll create our own simple config that mimics PHP 7+ for consistency
+ mkdir php-fpm.d; \
+ cp php-fpm.conf.default php-fpm.d/www.conf; \
+ { \
+ echo '[global]'; \
+ echo 'include=etc/php-fpm.d/*.conf'; \
+ } | tee php-fpm.conf; \
+ fi \
+ && { \
+ echo '[global]'; \
+ echo 'error_log = /proc/self/fd/2'; \
+ echo; \
+ echo '[www]'; \
+ echo '; if we send this to /proc/self/fd/1, it never appears'; \
+ echo 'access.log = /proc/self/fd/2'; \
+ echo; \
+ echo 'clear_env = no'; \
+ echo; \
+ echo '; Ensure worker stdout and stderr are sent to the main error log.'; \
+ echo 'catch_workers_output = yes'; \
+ } | tee php-fpm.d/docker.conf \
+ && { \
+ echo '[global]'; \
+ echo 'daemonize = no'; \
+ echo; \
+ echo '[www]'; \
+ echo 'listen = 9000'; \
+ } | tee php-fpm.d/zz-docker.conf
+
+EXPOSE 9000
+CMD ["php-fpm"]
+####
+
+# Download script to install PHP extensions and dependencies
+ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
+
+RUN chmod +x /usr/local/bin/install-php-extensions
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get update -q \
+ && DEBIAN_FRONTEND=noninteractive apt-get install -qq -y \
+ curl \
+ git \
+ zip unzip \
+# iconv, mbstring and pdo_sqlite are omitted as they are already installed
+ && PHP_EXTENSIONS=" \
+ amqp \
+ bcmath \
+ bz2 \
+ calendar \
+ event \
+ exif \
+ gd \
+ gettext \
+ imagick \
+ intl \
+ ldap \
+ mcrypt \
+ memcached \
+ mysql \
+ mysqli \
+ opcache \
+ pdo_mysql \
+ pdo_pgsql \
+ pgsql \
+ redis \
+ soap \
+ sockets \
+ xsl \
+ zip \
+ " \
+ && install-php-extensions $PHP_EXTENSIONS
+
+# Install Composer.
+ENV PATH=$PATH:/root/composer/vendor/bin \
+ COMPOSER_ALLOW_SUPERUSER=1 \
+ COMPOSER_HOME=/root/composer
+RUN cd /opt \
+ # Download installer and check for its integrity.
+ && curl -sSL https://getcomposer.org/installer > composer-setup.php \
+ && curl -sSL https://composer.github.io/installer.sha384sum > composer-setup.sha384sum \
+ && sha384sum --check composer-setup.sha384sum \
+ # Install Composer 2.
+ && php composer-setup.php --install-dir=/usr/local/bin --filename=composer --2 \
+ # Remove installer files.
+ && rm /opt/composer-setup.php /opt/composer-setup.sha384sum
diff --git a/compat/Makefile b/compat/Makefile
new file mode 100644
index 0000000..3c3b7aa
--- /dev/null
+++ b/compat/Makefile
@@ -0,0 +1,85 @@
+SHELL := /bin/bash
+ALL: build
+.PHONY: build test push
+
+IMAGE := chialab/php-compat
+VERSION ?= latest
+PHP_VERSION = $(firstword $(subst -, ,$(VERSION)))
+
+# Extensions.
+EXTENSIONS := \
+ amqp \
+ bcmath \
+ bz2 \
+ calendar \
+ event \
+ exif \
+ gd \
+ gettext \
+ iconv \
+ imagick \
+ intl \
+ ldap \
+ mbstring \
+ memcached \
+ mysqli \
+ OPcache \
+ pdo_mysql \
+ pdo_pgsql \
+ pgsql \
+ redis \
+ soap \
+ xsl \
+ zip \
+ sockets
+ifeq (,$(findstring $(PHP_VERSION), 7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4 latest alpine))
+ # Add more extensions to PHP < 7.2.
+ EXTENSIONS += mcrypt
+endif
+ifeq (,$(findstring $(PHP_VERSION), 7.0 7.1 7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4 latest alpine))
+ # Add more extensions to 5.x series images.
+ EXTENSIONS += mysql
+endif
+
+build:
+ @echo " =====> Building $(REGISTRY)$(IMAGE):$(VERSION)..."
+ docker image build --quiet -t $(REGISTRY)$(IMAGE):$(VERSION) .
+
+test:
+ @echo -e "=====> Testing loaded extensions... \c"
+ @if [[ -z `docker image ls $(REGISTRY)$(IMAGE) | grep "\s$(VERSION)\s"` ]]; then \
+ echo 'FAIL [Missing image!!!]'; \
+ exit 1; \
+ fi
+ @IMAGE_PHP_VERSION=`docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) sh -c '/bin/echo $$PHP_VERSION' | cut -d '.' -f 1,2`; \
+ if [[ "$(PHP_VERSION)" != "latest" && "$${IMAGE_PHP_VERSION}" != "$(PHP_VERSION)" ]]; then \
+ echo "FAIL [wrong PHP version: expected $(PHP_VERSION), got $${IMAGE_PHP_VERSION}]"; \
+ exit 1; \
+ fi
+ @modules=`docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) php -m`; \
+ for ext in $(EXTENSIONS); do \
+ if [[ "$${modules}" != *"$${ext}"* ]]; then \
+ echo "FAIL [$${ext}]"; \
+ exit 1; \
+ fi \
+ done
+ @if [[ "$(VERSION)" == *'-apache' ]]; then \
+ apache=`docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) apache2ctl -M 2> /dev/null`; \
+ if [[ "$${apache}" != *'rewrite_module'* ]]; then \
+ echo 'FAIL [mod_rewrite]'; \
+ exit 1; \
+ fi \
+ fi
+ @if [[ -z `docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) composer --version 2> /dev/null | grep '^Composer version 2\.[0-9][0-9]*'` ]]; then \
+ echo 'FAIL [Composer]'; \
+ exit 1; \
+ fi
+ @mariadbClientApi=`docker container run --rm $(REGISTRY)$(IMAGE):$(VERSION) php -i | grep -e "Client API.*MariaDB" | wc -l`; \
+ if [[ "$${mariadbClientApi}" -lt 4 ]]; then \
+ echo 'FAIL [MariaDB]'; \
+ exit 1; \
+ fi
+ @echo 'OK'
+
+push:
+ docker image push $(REGISTRY)$(IMAGE):$(VERSION)
diff --git a/compat/README.md b/compat/README.md
new file mode 100644
index 0000000..a3ee651
--- /dev/null
+++ b/compat/README.md
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+ Docker PHP images
+
+
+
+
+
+
+
+
+
+
+---
+
+Compatibility docker images.
+
+### PHP 5.6
+
+Built from the latest official PHP 5.6 Dockerfiles ([this](https://github.com/docker-library/php/tree/783878384a8f3953ed571e5a34ba0fe546726c85) commit),
+with PHP compiled to use MariaDB's `libmysqlclient` connector. This fixes connections with MySQL 8.0+, which uses a default
+collation not recognized by the official image's `mysqlnd` connector (`utf8mb4`).
+
+## Available tags
+- `5.6`
+- `5.6-apache`
+- `5.6-fpm`
+
+## Installed extensions
+The following modules and extensions have been enabled,
+in addition to those you can already find in the [official PHP image](https://hub.docker.com/r/_/php/):
+
+- `amqp`
+- `bcmath`
+- `bz2`
+- `calendar`
+- `event`
+- `exif`
+- `gd`
+- `gettext`
+- `iconv`
+- `imagick`
+- `intl`
+- `ldap`
+- `mbstring`
+- `mcrypt` (_only PHP ≤ 7.1_)
+- `memcached`
+- `mysql` (_only PHP 5.x_)
+- `mysqli`
+- `pcov`
+- `pdo_mysql`
+- `pdo_pgsql`
+- `pgsql`
+- `redis`
+- `soap`
+- `sockets`
+- `xsl`
+- `Zend OPcache`
+- `zip`
+
+You will probably not need all this stuff. Even if having some extra extensions loaded ain't a big issue in most cases (especially in a development environment), you will very likely want to checkout this repository, remove unwanted extensions from the `Dockerfile`, and build your own image — for sometimes removing is easier than adding. 😉
+
+## Composer
+[Composer](https://getcomposer.org) is installed globally in all images. Please, refer to their documentation for usage hints.
+Since 2020/11/01 both version 1 and 2 are installed, available through `composer1` and `composer2` commands respectively (`composer` in now a symlink to `composer2`).
+[Prestissimo (composer plugin)](https://github.com/hirak/prestissimo) is installed globally in all images, for use with Composer version 1. It's a plugin that downloads packages in parallel to speed up the installation process of Composer packages.
+
+## Contributing
+If you find an issue, or have a special wish not yet fulfilled, please [open an issue on GitHub](https://github.com/chialab/docker-php/issues) providing as many details as you can (the more you are specific about your problem, the easier it is for us to fix it).
+
+Pull requests are welcome, too! 😁 Please, run `make build` and `make test` before attempting a pull request. Also, it would be nice if you could stick to the [best practices for writing Dockerfiles](https://docs.docker.com/articles/dockerfile_best-practices/).
+
+---
+
+## License
+
+Docker PHP Images is released under the [MIT](https://github.com/chialab/docker-php/blob/master/LICENSE) license.
diff --git a/dev/README.md b/dev/README.md
index 66fc1c1..4218d3f 100644
--- a/dev/README.md
+++ b/dev/README.md
@@ -9,7 +9,7 @@
-
+
diff --git a/pcov/README.md b/pcov/README.md
index d8de3a2..b6e4700 100644
--- a/pcov/README.md
+++ b/pcov/README.md
@@ -9,7 +9,7 @@
-
+
diff --git a/xhprof/README.md b/xhprof/README.md
index 2983023..cf26553 100644
--- a/xhprof/README.md
+++ b/xhprof/README.md
@@ -9,7 +9,7 @@
-
+