Install node.js official binary on alpine

17.7k views Asked by At

I'm trying to install node official binary on alpine docker.

wget https://nodejs.org/dist/v14.4.0/node-v14.4.0-linux-x64.tar.xz

tar -xvf node-v14.4.0-linux-x64.tar.xz And once I try to run it:

~/node-v14.4.0-linux-x64/bin # ./node 
sh: ./node: not found

Although the file is here, I have the permission and it is executable

~/node-v14.4.0-linux-x64/bin # ls -la
total 70376
drwxr-xr-x 2 root root     4096 Oct  7 11:53 .
drwxr-xr-x 6 1001 1001     4096 Oct  7 11:53 ..
-rwxr-xr-x 1 root root 72052312 Jun  2 14:33 node
lrwxrwxrwx 1 root root       38 Oct  7 11:53 npm -> ../lib/node_modules/npm/bin/npm-cli.js
lrwxrwxrwx 1 root root       38 Oct  7 11:53 npx -> ../lib/node_modules/npm/bin/npx-cli.js

When I do the same action on ubuntu it works.

5

There are 5 answers

3
Gustavo Kawamoto On BEST ANSWER

This happens because alpine uses musl instead of glibc, and the binaries distributed from node's website are built against glibc.

Here are a few solutions for your problem, in order of preference (and why):

  1. Use node's official image instead of trying to install it from a alpine base image: that's because there are different dependencies and things to setup before having a working node image (certificates, tls libraries, etc). This is the most recommended.

  2. Installing node via apk: node is available at alpine's official package manager apk, and you can install it by simply running apk add nodejs. The only problem here is that the version that's available in the repository is the LTS (12.18.4 as of 2020-10-07).

  3. Installing/building a compability layer for glibc in alpine: this is not recommended at all, since alpine is built over musl and running glibc is not a good practice and can lead to things breaking. Even installing the official libc6-compat may lead to problems:

Running node using libc6-compat:

$ ./node
Error relocating ./node: gnu_get_libc_version: symbol not found
Error relocating ./node: __register_atfork: symbol not found
Error relocating ./node: __strdup: symbol not found
Error relocating ./node: setcontext: symbol not found
Error relocating ./node: makecontext: symbol not found
Error relocating ./node: backtrace: symbol not found
Error relocating ./node: getcontext: symbol not found

Running node using this answer's suggestion for glibc:

$ ./node
./node: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

Stick to node's official image (solution 1) and things should work out fine :)

1
ogbofjnr On

Other binary don't work on alpine, need to build it manually as in here https://github.com/nodejs/docker-node/blob/80ded64083b5c9be7853d9d3634a22a96e15e92d/14/alpine3.10/Dockerfile

1
Sr. Libre On

You need to download an unofficial build that is built against musl

wget https://unofficial-builds.nodejs.org/download/release/v14.4.0/node-v14.4.0-linux-x64-musl.tar.xz

Note: Unofficial builds are linked in the Node.js project then from my point of view does no represent a security issue.

1
rozaydin On

I tried using the old repositories but, found Sr. Libre's above answer was the easiest to use.

add the following to the Dockerfile

RUN wget https://unofficial-builds.nodejs.org/download/release/v12.22.3/node-v12.22.3-linux-x64-musl.tar.gz
RUN tar -xvf node-v12.22.3-linux-x64-musl.tar.gz
RUN rm node-v12.22.3-linux-x64-musl.tar.gz

RUN ln -s /var/www/node-v12.22.3-linux-x64-musl/bin/node /usr/bin/node
RUN ln -s /var/www/node-v12.22.3-linux-x64-musl/bin/npm /usr/bin/npm

Check from Docker container and you will see proper versions:

bash-5.1# node --version
v12.22.3
bash-5.1# npm -v
6.14.13
bash-5.1# 

Following URL contains a list of builds you can use:

https://unofficial-builds.nodejs.org/download/release/

Just ensure you pick the ones with musl suffix.

0
davchs On

You can use a multi-stage build to copy the necessary files from the node:XX.XX.X-alpine image to your custom image. In the example below, the first FROM statement pulls the Node.js image tagged 18.17.1-alpine, and the second FROM statement initializes a new stage for your custom image in this example fpm_dev. The COPY --from=node lines then copy various directories from the node image to your custom image. hth

# Use the official Node.js Alpine image as the first stage
FROM node:18.17.1-alpine AS node

# Initialize the second stage with your custom image
FROM fpm_dev AS cli_dev

# Copy Node.js, npm, and yarn related files and directories from the first stage to the second stage
COPY --from=node /usr/lib /usr/lib                      # Libraries
COPY --from=node /usr/local/share /usr/local/share      # Shared assets and data
COPY --from=node /usr/local/lib /usr/local/lib          # More libraries
COPY --from=node /usr/local/include /usr/local/include  # Header files
COPY --from=node /usr/local/bin /usr/local/bin          # Binaries
COPY --from=node /opt /opt                              # Optional software packages