php: docker-php-ext-install fails but returns 0

There is one quite annoying thing with current docker-php-ext-install.

It runs extensions sources compilation in subshell docker-php-ext-install:93-104. So if compilation of some extension fails, the set -e has no effect on it and docker-php-ext-install continues to execute. This lead to very bad situations when docker build succeeds, but in fact extensions are not installed.

Issue can be easily reproduced with the following Dockerfile:

FROM php:alpine

RUN docker-php-ext-install \
           gd \
           opcache

It builds successfully. However, if we php -i inside built container, there is no gd extension installed. Why? 'Cause docker-php-ext-install gd’s dependencies where not satisfied (libpng, libjpeg, etc.) and docker build log confirms it with following lines:

checking for FreeType 2... no
checking whether to enable truetype string function in GD... no
checking whether to enable JIS-mapped Japanese font support in GD... no
configure: error: png.h not found.

If we remove that subshell execution:

FROM php:alpine

RUN sed -i -r 's/^\t+\($//g' /usr/local/bin/docker-php-ext-install \
 && sed -i -r 's/^\t+\)$//g' /usr/local/bin/docker-php-ext-install

RUN docker-php-ext-install \
           gd \
           opcache

The docker build fails at compiling gd step as expected.

Is that subshell really required there?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 15 (10 by maintainers)

Most upvoted comments

@SG5, that is normal behavior; the docker-php-* scripts do not install any run dependencies. You need to install any dependencies that gd may require like the example in the docs for the Debian based image. It should be a similar setup for the Alpine based image.

FROM php:7.0-fpm
RUN apt-get update && apt-get install -y \
		libfreetype6-dev \
		libjpeg62-turbo-dev \
		libmcrypt-dev \
		libpng12-dev \
	&& docker-php-ext-install -j$(nproc) iconv mcrypt \
	&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
	&& docker-php-ext-install -j$(nproc) gd

For example, if we make the following change to docker-php-ext-configure, then docker-php-ext-install /some/absolute/path will also be acceptable usage of this script (which was previously acceptable IIRC, but got lost in a refactoring somewhere):

diff --git a/docker-php-ext-configure b/docker-php-ext-configure
index 21f4320..2a6f839 100755
--- a/docker-php-ext-configure
+++ b/docker-php-ext-configure
@@ -10,9 +10,10 @@ if [ -z "$srcExists" ]; then
        touch /usr/src/php/.docker-delete-me
 fi
 
+cd /usr/src/php/ext
+
 ext="$1"
-extDir="/usr/src/php/ext/$ext"
-if [ -z "$ext" ] || [ ! -d "$extDir" ]; then
+if [ -z "$ext" ] || [ ! -d "$ext" ]; then
        echo >&2 "usage: $0 ext-name [configure flags]"
        echo >&2 "   ie: $0 gd --with-jpeg-dir=/usr/local/something"
        echo >&2
@@ -46,6 +47,6 @@ if [ "$pm" = 'apk' ]; then
 fi
 
 set -x
-cd "$extDir"
+cd "$ext"
 phpize
 ./configure "$@"

Wow, wow, wow! Something interesting was found here!

First of all, I’m sorry for providing “buggy” PoC, which lead to wrong conclusions. Actually there is no sense of opcache ext there. But the issue I’ve pointed to still remains.

Having Dockerfile like:

FROM php:alpine
RUN docker-php-ext-install gd

We have next successful result of docker build (you may just check it):

$ docker build --no-cache -t test .
......................
configure: error: png.h not found.
WARNING: Ignoring APKINDEX.167438ca.tar.gz: No such file or directory
WARNING: Ignoring APKINDEX.a2e6dac0.tar.gz: No such file or directory
(1/24) Purging .phpize-deps (0)
......................
(24/24) Purging libgomp (5.3.0-r0)
Executing busybox-1.24.2-r11.trigger
OK: 16 MiB in 25 packages
 ---> 598ce831f3b8
Removing intermediate container c8afb81a0fca
Successfully built 598ce831f3b8

While if we are using sed to remove subshell:

FROM php:alpine
RUN sed -i -r 's/^\t+\($//g' /usr/local/bin/docker-php-ext-install \
 && sed -i -r 's/^\t+\)$//g' /usr/local/bin/docker-php-ext-install
RUN docker-php-ext-install gd

Build fails as expected at configure step:

$ docker build --no-cache -t test .
......................
configure: error: png.h not found.
The command '/bin/sh -c docker-php-ext-install gd' returned a non-zero code: 1

And now is interesting…

I didn’t know about -e inheritance. And reproduced your example in my macOS terminal:

$ sh -c 'set -e; echo "1"; (echo "2"; false; echo "3"); echo "4"'
1
2

It really works. But why those Dockerfiles behave so?

That’s why:

$ docker run --rm -it alpine sh
/ # sh -c 'set -e; echo "1"; (echo "2"; false; echo "3"); echo "4"'
1
2
4

@tyranron I was about to look at how to solve this and make a PR when I found this issue. I guess you should make a PR 😃

just to avoid changing for working directory for the rest of the script (even if there is not much going on after that)

--- docker-php-ext-install.orig
+++ docker-php-ext-install
@@ -90,8 +90,7 @@
 fi

 for ext in $exts; do
-   (
        cd "$ext"
        [ -e Makefile ] || docker-php-ext-configure "$ext"
        make -j"$j"
        make -j"$j" install
@@ -101,7 +100,6 @@
            -exec basename '{}' ';' \
                | xargs -r docker-php-ext-enable
        make -j"$j" clean
+      cd ..
-   )
 done

 if [ "$pm" = 'apk' ] && [ -n "$apkDel" ]; then