benelori
benelori

Reputation: 78

icu-dev library removes /bin/sh or messes up the image entry point

I am trying to build an optimized PHP image. The strategy that I chose, was to install and compile everything in a build stage and then copy the extensions to a new stage and enable them. This allows me to shed 200MB.

All is good until the intl extension. This extension needs the icu-dev library, but once I install that, /bin/sh disappears, or somehow the entry point gets all messed up. This is very low level stuff and I don't really know how to even search for the issue.

# Prepare compiled extensions
FROM php:8.1-cli-alpine as build

RUN apk --no-cache add autoconf build-base icu-dev

RUN docker-php-ext-install intl

FROM php:8.1-cli-alpine

COPY --from=build /usr/local/lib/php/extensions/no-debug-non-zts-20210902/intl.so /usr/local/lib/php/extensions/no-debug-non-zts-20210902/intl.so

RUN apk --no-cache add icu-dev

RUN docker-php-ext-enable intl

This is the output of the image build

[+] Building 1.6s (10/10) FINISHED                                                                                                                                                                                                                                        
 => [internal] load build definition from Dockerfile                                                                                                                                                                                                                 0.0s
 => => transferring dockerfile: 429B                                                                                                                                                                                                                                 0.0s
 => [internal] load .dockerignore                                                                                                                                                                                                                                    0.0s
 => => transferring context: 2B                                                                                                                                                                                                                                      0.0s
 => [internal] load metadata for docker.io/library/php:8.1-cli-alpine                                                                                                                                                                                                1.3s
 => [auth] library/php:pull token for registry-1.docker.io                                                                                                                                                                                                           0.0s
 => [build 1/3] FROM docker.io/library/php:8.1-cli-alpine@sha256:858d56e3ee12e138a9119380fb361a5b01f1ff9369d372ef73042b6cd4753f25                                                                                                                                    0.0s
 => CACHED [build 2/3] RUN apk --no-cache add autoconf build-base icu-dev                                                                                                                                                                                            0.0s
 => CACHED [build 3/3] RUN docker-php-ext-install intl                                                                                                                                                                                                               0.0s
 => CACHED [stage-1 2/4] COPY --from=build /usr/local/lib/php/extensions/no-debug-non-zts-20210902/intl.so /usr/local/lib/php/extensions/no-debug-non-zts-20210902/intl.so                                                                                           0.0s
 => CACHED [stage-1 3/4] RUN apk --no-cache add icu-dev                                                                                                                                                                                                              0.0s
 => ERROR [stage-1 4/4] RUN docker-php-ext-enable intl                                                                                                                                                                                                               0.3s
------                                                                                                                                                                                                                                                                    
 > [stage-1 4/4] RUN docker-php-ext-enable intl:
#10 0.251 container_linux.go:380: starting container process caused: exec: "/bin/sh": stat /bin/sh: no such file or directory
------
executor failed running [/bin/sh -c docker-php-ext-enable intl]: exit code: 1
make: *** [Makefile:4: build] Error 1

Here's a reproduction repo, in case anyone is interested

https://github.com/benelori/icu-dev-reproduction

EDIT:

Unfortunately I did not provide all the details:

  1. The command I ran for building the image was DOCKER_BUILDKIT=1 docker build . -t test/icu:latest

  2. Docker version 20.10.12, build e91ed57

It seems like this is not reproducible for everyone, so I do not know what else to provide.

In the end though, if I don't enable build kit, then the build command runs successfully, therefore I marked the answer below as accepted.

Upvotes: 0

Views: 621

Answers (1)

Zeitounator
Zeitounator

Reputation: 44760

I'm not exactly sure what you are trying to achieve here with your multistage build but this clearly messes up your extension. You don't really need a multistage here as alpine apk provides tools to deal with build dependencies.

I did not fully dig in the process so that might be further optimized, but here is a Dockerfile which:

  • Installs required build packages as a virtual package
  • Installs icu-dev and the php intl extension. Note that the extension is installed enabled so there is no need to do that in a separate step
  • Removes the build dependencies virtual package once this is done

All of this takes place in a single layer so you end up with only what is strictly needed (i.e. the intl extension and required icu-dev package, unless I forgot some additional possible cleanup...)

FROM php:8.1-cli-alpine

RUN apk add --no-cache autoconf build-base --virtual build_deps && \
    apk add --no-cache icu-dev && \
    docker-php-ext-install intl && \
    apk del build_deps

You can build from that Dockerfile file as

docker build -t test:test .

and see the extension is available as expected:

$ docker run -it --rm test:test sh -c "php -i | grep -A 7 intl"
Additional .ini files parsed => /usr/local/etc/php/conf.d/docker-php-ext-intl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sodium.ini

PHP API => 20210902
PHP Extension => 20210902
Zend Extension => 420210902
Zend Extension Build => API420210902,NTS
PHP Extension Build => API20210902,NTS
--
intl

Internationalization support => enabled
ICU version => 69.1
ICU Data version => 69.1
ICU Unicode version => 13.0

Directive => Local Value => Master Value
intl.default_locale => no value => no value
intl.error_level => 0 => 0
intl.use_exceptions => Off => Off

json

json support => enabled

libxml

The resulting image is 135MB (compared to 366MB without removing the build dependencies). This makes it roughly 40MB more than the base image which is 94.2MB at time of this writing.

Upvotes: 1

Related Questions