Phantomjs for npm in alpine-based docker image

Make npm phantomjs-prebuilt package compatible with alpine-based docker image.

Problem

musl-libc vs glibc

alpine uses musl-libc as its C library instead of glibc to shrink down the image size and improve performance 1.

However phantomjs doesn’t get compiled with musl-libc which cripples phantomjs-prebuilt node package inside the container. The cause was pinned down to the missing ld-linux-x86-64.so.2.

phantomjs error

It appears there is no fix for this even after so long.

Solution

Dockerize

One approach is to Dockerize phantomjs into linux executables inside a glibc compatible base (Debian or Ubuntu):

// download phantomjs
mkdir /tmp && cd /tmp
curl -o phantomjs.tar.bz2 \

    -L https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2

// untar and dockerize phantomjs
tar -jxvf phantomjs.tar.bz2

dockerize -n -o phantomjsDir -e /tmp/phantomjs-2.1.1-linux-x86_64  \

    -a /bin/dash /bin/sh -a /usr/share/fonts /usr/share -a /etc/ssl /etc  \ 
    -a /etc/fonts /etc \

    /tmp/phantomjs-2.1.1-linux-x86_64 /usr/bin/curl

// tar the executables but without phantomjs binaries
cd phantomjsDir
tar -zcf phantomjs.tar.gz ./lib ./lib64 ./usr/lib

Which gives us a phantomjs.tar.gz with the following structure:

│── lib
│   └── x86_64-linux-gnu
│       ├── libcom_err.so.2
│       ├── libcrypto.so.1.0.0  
│       ├── libcrypt.so.1
│       ├── libc.so.6
│       ├── libdl.so.2
│       ├── libexpat.so.1
│       ├── libgcc_s.so.1
│       ├── libgcrypt.so.11
│       ├── libgpg-error.so.0
│       ├── libkeyutils.so.1
│       ├── libm.so.6
│       ├── libnss_compat.so.2
│       ├── libnss_dns.so.2
│       ├── libnss_files.so.2
│       ├── libpng12.so.0
│       ├── libpthread.so.0
│       ├── libresolv.so.2
│       ├── librt.so.1
│       ├── libssl.so.1.0.0
│       └── libz.so.1
├── lib64
│   └── ld-linux-x86-64.so.2
└── usr
│   └── lib
│       └── x86_64-linux-gnu
│           ├── libasn1.so.8
│           ├── libcurl.so.4
│           ├── libffi.so.6
│           ├── libfontconfig.so.1
│           ├── libfreetype.so.6
│           ├── libgnutls.so.26
│           ├── libgssapi_krb5.so.2
│           ├── libgssapi.so.3
│           ├── libhcrypto.so.4
│           ├── libheimbase.so.1
│           ├── libheimntlm.so.0
│           ├── libhx509.so.5
│           ├── libidn.so.11
│           ├── libk5crypto.so.3
│           ├── libkrb5.so.26
│           ├── libkrb5.so.3
│           ├── libkrb5support.so.0
│           ├── liblber-2.4.so.2
│           ├── libldap_r-2.4.so.2
│           ├── libp11-kit.so.0
│           ├── libroken.so.18
│           ├── librtmp.so.0
│           ├── libsasl2.so.2
│           ├── libsqlite3.so.0
│           ├── libstdc++.so.6
│           ├── libtasn1.so.6
│           └── libwind.so.0

Then mount phantomjs.tar.gz into the alpine image we are going to build.

tar -zxf phantomjs.tar.gz /

phantomjs-prebuilt should now work fine in alpine-based docker containers.

Footnote
Last updated