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 does not 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's nice about PECL packages is that the source is
ready to be compiled and the URLs to get the packages is consistent. So I started investigating that
route.
A script to get packages from PECL repository
To help me in the endeavour 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 obtained 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 obtain 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?