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
What about `COPY –from=alpine:3.13 /usr/lib/preloadable_libiconv.so /usr/lib/preloadable_libiconv.so`
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.