In a previous article I explained how to install PHP extensions from source for PEAR is no longer available starting PHP 7.4 and PECL is bundled with it. I think I found a simpler solution that works with PECL packages and still doesn't require the PECL command.
The issue I had installing extensions from source is that some are tricky, especially when they use Git submodules (I'm looking at you mongodb
). What is nice about PECL packages is that the source is ready to be compiled and the URLs to get the packages are consistent. So I started investigating that route.
A script to get packages from the PECL repository
To help me in the endeavor, I created a shell script, similar to the script already available in the PHP base image. I called it docker-php-ext-get
, following the naming pattern.
#!/usr/bin/env sh
set -e
dir=/usr/src/php
if [ ! -f "$dir/.docker-extracted" ]; then
echo >&2 "error: PHP source required, run 'docker-php-source extract' first"
exit 1
fi
dir="$dir/ext"
usage() {
echo "usage: $0 module-name module-version"
echo " ie: $0 redis 4.3.0"
}
name=$1
version=$2
if [ -z "$name" ]; then
usage >&2
exit 1
fi
if [ -z "$version" ]; then
usage >&2
exit 1
fi
mkdir -p "$dir/$name"
curl -fsSL "https://pecl.php.net/get/$name-$version.tgz" | tar xvz -C "$dir/$name" --strip 1
Using docker-php-ext-get
in a Dockerfile
docker-php-ext-get
needs to be copied inside the Docker image to be used, which is easy to do if
it sits next to the Dockerfile, like the official scripts are. It needs to run between
docker-docker-php-source extract
and docker-docker-php-source delete
, it works with one package
at a time, and the exact version needs to be provided (which has the side effect of keeping the
Dockerfile reproducible).
The following example demonstrates how to get and install mongodb
v1.5.2:
FROM php:7.4.0alpha1-fpm-stretch
COPY docker-php-ext-get /usr/local/bin/
RUN docker-php-source extract &&\
docker-php-ext-get mongodb 1.5.2 &&\
docker-php-ext-install mongodb &&\
docker-php-source delete
To check if the extension is installed properly you can run the following commands:
$ docker build -t php74-fpm-with-mongodb .
$ docker run php74-fpm-with-mongodb php -i | grep mongodb
You should get the following result:
Additional .ini files parsed => /usr/local/etc/php/conf.d/docker-php-ext-mongodb.ini,
mongodb
mongodb.debug => no value => no value
Updating our Dockerfile
This is the Dockerfile we got with the previous method:
# This is the base image for FPM containers, to speed up building.
# https://hub.docker.com/_/php/
FROM php:7.3.2-fpm-stretch AS ext-mongodb
ENV EXT_MONGODB_VERSION=1.5.2
RUN docker-php-source extract \
&& apt-get update && apt-get install git -y \
&& git clone --branch $EXT_MONGODB_VERSION --depth 1 https://github.com/mongodb/mongo-php-driver.git /usr/src/php/ext/mongodb \
&& cd /usr/src/php/ext/mongodb && git submodule update --init \
&& docker-php-ext-install mongodb
FROM php:7.3.2-fpm-stretch
# ext-mongodb
COPY --from=ext-mongodb /usr/local/etc/php/conf.d/docker-php-ext-mongodb.ini /usr/local/etc/php/conf.d/docker-php-ext-mongodb.ini
COPY --from=ext-mongodb /usr/local/lib/php/extensions/no-debug-non-zts-20180731/mongodb.so /usr/local/lib/php/extensions/no-debug-non-zts-20180731/mongodb.so
ENV EXT_APCU_VERSION=5.1.17 EXT_REDIS_VERSION=4.3.0 EXT_IGBINARY_VERSION=3.0.1
RUN docker-php-source extract \
# ext-opache
&& docker-php-ext-enable opcache \
# ext-igbinary
&& mkdir -p /usr/src/php/ext/igbinary \
&& curl -fsSL https://github.com/igbinary/igbinary/archive/$EXT_IGBINARY_VERSION.tar.gz | tar xvz -C /usr/src/php/ext/igbinary --strip 1 \
&& docker-php-ext-install igbinary \
# ext-redis
&& mkdir -p /usr/src/php/ext/redis \
&& curl -fsSL https://github.com/phpredis/phpredis/archive/$EXT_REDIS_VERSION.tar.gz | tar xvz -C /usr/src/php/ext/redis --strip 1 \
&& docker-php-ext-configure redis --enable-redis-igbinary \
&& docker-php-ext-install redis \
# ext-apcu
&& mkdir -p /usr/src/php/ext/apcu \
&& curl -fsSL https://github.com/krakjoe/apcu/archive/v$EXT_APCU_VERSION.tar.gz | tar xvz -C /usr/src/php/ext/apcu --strip 1 \
&& docker-php-ext-install apcu \
# ext-bcmath, ext-sockets
&& docker-php-ext-install bcmath sockets
And this is the Dockerfile we get with the new method:
# This is the base image for FPM containers, to speed up building.
# https://hub.docker.com/_/php/
FROM php:7.3.2-fpm-stretch
COPY docker-php-ext-get /usr/local/bin/
RUN docker-php-source extract &&\
docker-php-ext-enable opcache &&\
docker-php-ext-get igbinary 3.0.1 &&\
docker-php-ext-install igbinary &&\
docker-php-ext-get redis 4.3.0 &&\
docker-php-ext-configure redis --enable-redis-igbinary &&\
docker-php-ext-install redis &&\
docker-php-ext-get apcu 5.1.17 &&\
docker-php-ext-install apcu &&\
docker-php-ext-get mongodb 1.5.2 &&\
docker-php-ext-install mongodb &&\
docker-php-ext-install bcmath sockets
Much simpler, don't you agree?