Alpine Linux PHP + iconv fix

To use PHP with iconv on Alpine Linux – in a Docker container for example – you need to use the preloadable iconv library, which was previously provided with the gnu-libiconv package, but was removed after Alpine v3.13. After recently rebuilding an Alpine image and running a PHP script that required iconv, I saw the following error:

Notice: iconv(): Wrong charset, conversion from `UTF-8' to `UTF-8//IGNORE' is not allowed

To work around it I installed the gnu-libiconv package from the v3.13 repo. For my projects I went ahead and exported the preloadable binary once it was built as well so that I could just COPY it into the image instead of building it – in my case it’s only for Alpine after all.

You can do this by using an Alpine image tag of alpine:3.13 to add gnu-libiconv and compile /usr/lib/preloadable_libiconv.so, then copy it to a volume to save the binary once the container exits – the output folder is called ./out in this example.

% docker run -v $(pwd)/out:/out -it alpine:3.13 \
/bin/sh -c 'apk add --no-cache gnu-libiconv && cp -f /usr/lib/preloadable_libiconv.so /out/preloadable_libiconv.so'
      
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
(1/1) Installing gnu-libiconv (1.15-r3)
Executing busybox-1.32.1-r6.trigger
OK: 8 MiB in 15 packages

% ls -la out/preloadable_libiconv.so                                                                                                                             
-rw-r--r--  1 justin  staff  1005216 Apr 23 14:32 out/preloadable_libiconv.so

Once you have the prebuilt binary you can use COPY in your Dockerfile to use it without needing to build it.


# copy preloadable_libiconv.so from prebuilt
COPY /rootfs/usr/lib/preloadable_libiconv.so /usr/lib/preloadable_libiconv.so
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php

If you prefer to install the older package that includes the preloadable binary in a different Alpine Dockerfile you can specify an older repository in a RUN command, like so:

FROM wordpress:5.7.1-php7.4-fpm-alpine
# ... some config
RUN apk add --no-cache \
    --repository http://dl-cdn.alpinelinux.org/alpine/v3.13/community/ \
    --allow-untrusted \
    gnu-libiconv
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php

You may also like...

2 Responses

  1. Sebastian Mendel says:

    What about `COPY –from=alpine:3.13 /usr/lib/preloadable_libiconv.so /usr/lib/preloadable_libiconv.so`

    • Justin Silver says:

      I don’t think that will work because gnu-libiconv isn’t installed by default so the file will be missing from the base alpine:3.13 image. You could use a build stage in the Dockerfile to do something similar though.

      FROM alpine:3.13 AS iconv-build
      RUN apk add --no-cache gnu-libiconv
      
      FROM alpine:latest 
      COPY –from=iconv-build /usr/lib/preloadable_libiconv.so /usr/lib/preloadable_libiconv.so
      ...
      

Leave a Reply

Your email address will not be published. Required fields are marked *