Installing specific version of NodeJS and NPM on Alpine docker image
Asked Answered
S

4

22

I need to use a standard Alpine docker image and install a specific version of Node and NPM. Heres is my attempt so far:

FROM alpine:3.17.2

RUN apk update
RUN apk upgrade
RUN apk add bash git helm openssh yq github-cli

RUN apk add \
    curl \
    docker \
    openrc

# nvm environment variables
ENV NVM_DIR /usr/local/nvm
ENV NVM_VERSION 0.39.3
ENV NODE_VERSION 18.16.0

# install nvm
# https://github.com/creationix/nvm#install-script
RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v$NVM_VERSION/install.sh | bash

# install node and npm
RUN source $NVM_DIR/nvm.sh \
    && nvm install $NODE_VERSION \
    && nvm alias default $NODE_VERSION \
    && nvm use default

# add node and npm to path so the commands are available
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH

RUN ls -asl $NVM_DIR/versions/node/v$NODE_VERSION/bin
RUN ls -asl $NVM_DIR/versions/node/v$NODE_VERSION/lib/node_modules/npm/bin

RUN $NVM_DIR/versions/node/v$NODE_VERSION/bin/node -v

RUN $NVM_DIR/versions/node/v$NODE_VERSION/bin/npm install --global yarn

# Start docker on boot
RUN rc-update add docker boot

# Default commands to bash
ENTRYPOINT ["bash"]

I am getting this:

#7 [ 4/10] RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.39.3/install.sh | bash
#7 sha256:76a5a08c3c01075cd22585bc1f3df8f47fe258b116742db843cea6fa553a09c6
#7 0.181   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
#7 0.182                                  Dload  Upload   Total   Spent    Left  Speed
100 15916  100 15916    0     0  57463      0 --:--:-- --:--:-- --:--:-- 60287
#7 0.478 => Downloading nvm from git to '/usr/local/nvm'
=> Cloning into '/usr/local/nvm'...
#7 3.239 * (HEAD detached at FETCH_HEAD)
#7 3.240   master
#7 3.268 => Compressing and cleaning up git repository
#7 3.307
#7 3.338 => Profile not found. Tried ~/.bashrc, ~/.bash_profile, ~/.zprofile, ~/.zshrc, and ~/.profile.
#7 3.338 => Create one of them and run this script again
#7 3.338    OR
#7 3.338 => Append the following lines to the correct file yourself:
#7 3.338
#7 3.338 export NVM_DIR="/usr/local/nvm"
#7 3.338 [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
#7 3.338
#7 3.440 => Installing Node.js version 18.16.0
#7 4.948 Downloading and installing node v18.16.0...
#7 5.646 Downloading https://nodejs.org/dist/v18.16.0/node-v18.16.0-linux-x64.tar.gz...
######################################################################## 100.0%
#7 8.333 Computing checksum with sha256sum
#7 8.832 Checksums matched!
#7 11.93 Now using node v18.16.0 (npm v)
#7 12.41 Creating default alias: default -> 18.16.0 (-> v18.16.0 *)
#7 12.63 Failed to install Node.js 18.16.0
#7 12.63 => Close and reopen your terminal to start using nvm or run the following to use it now:
#7 12.63
#7 12.63 export NVM_DIR="/usr/local/nvm"
#7 12.63 [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
#7 DONE 12.7s

I am not sure about the "Failed to install Node.js 18.16.0" message, as you will see in my tests with "ls" it seems to be installed?

First I "ls" the bin directory where I expect node to be installed:

RUN ls -asl /usr/local/nvm/versions/node/v18.16.0/bin
#9 sha256:42ba843ab812861bf82e0e493e211095cc749408940b5ec21ce94fabe3997538
#9 0.138 total 88820
#9 0.141      4 drwxr-xr-x    2 1000     1000          4096 Apr 27 07:35 .
#9 0.141      4 drwxr-xr-x    6 root     root          4096 Apr 27 07:35 ..
#9 0.141      0 lrwxrwxrwx    1 root     root            45 Apr 27 07:35 corepack -> ../lib/node_modules/corepack/dist/corepack.js
#9 0.141  88812 -rwxr-xr-x    1 1000     1000      90940576 Apr 12 05:31 node
#9 0.141      0 lrwxrwxrwx    1 root     root            38 Apr 27 07:35 npm -> ../lib/node_modules/npm/bin/npm-cli.js
#9 0.141      0 lrwxrwxrwx    1 root     root            38 Apr 27 07:35 npx -> ../lib/node_modules/npm/bin/npx-cli.js
#9 DONE 0.1s

This seem ok to me, is it not?

My other "ls" gives this:

RUN ls -asl /usr/local/nvm/versions/node/v18.16.0/lib/node_modules/npm/bin
#10 sha256:c2872332dbb58f191400fa23211a691db9a5f5dc07425bc9d3c83bf1cafb31f8
#10 0.141 total 36
#10 0.144      4 drwxr-xr-x    3 1000     1000          4096 Apr 27 07:35 .
#10 0.144      4 drwxr-xr-x    7 1000     1000          4096 Apr 27 07:35 ..
#10 0.144      4 drwxr-xr-x    2 1000     1000          4096 Apr 27 07:35 node-gyp-bin
#10 0.144      4 -rwxr-xr-x    1 1000     1000          1365 Oct 11  2022 npm
#10 0.144      4 -rwxr-xr-x    1 1000     1000            54 Oct 11  2022 npm-cli.js
#10 0.144      4 -rwxr-xr-x    1 1000     1000           483 Oct 11  2022 npm.cmd
#10 0.144      4 -rwxr-xr-x    1 1000     1000          1567 Oct 11  2022 npx
#10 0.144      4 -rwxr-xr-x    1 1000     1000          2922 Dec  7 06:00 npx-cli.js
#10 0.144      4 -rwxr-xr-x    1 1000     1000           539 Oct 11  2022 npx.cmd
#10 DONE 0.2s

So npm is here also, looking good?

In my initial post here, I was giving the wrong error message, I am sorry. The error message was from my local machine, which is a Mac with the M2 CPU, and I believe this caused that error, but that is for another day. I need it to run on the build servers, where we are running linux on amd64 so there I have a different error, the following error:

Step 14/17 : RUN $NVM_DIR/versions/node/v$NODE_VERSION/bin/node -v
 ---> Running in d63ec3b287d9
/bin/sh: /usr/local/nvm/versions/node/v18.16.0/bin/node: not found
The command '/bin/sh -c $NVM_DIR/versions/node/v$NODE_VERSION/bin/node -v' returned a non-zero code: 127

Error: Process completed with exit code 127.

So my "ls" say node is there but when I try and run it, it is not?

Best regards
Søren

Sickert answered 26/4, 2023 at 11:3 Comment(8)
Why not use existing node:<version>-alpine images? Also, I see you are using QEMU, which may interfere with the binaries that are being downloaded.Crown
I am required to use pre alpine :)Sickert
What do you mean by that? Required by who/what?Crown
Someone on my team with more stars on their shoulder than me ;)Sickert
Sounds like that person doesn't understand Docker? Look at the Dockerfile for node:current-alpine and you clearly see FROM alpine as a base. Don't reinvent the wheel.Crown
forget (for this requirement) about "nvm", nvm is "node version manager" (for "localhost" normally!), when you need to "manage your node version", just use another image/the $NODE_VERSION ARG (which can be passed to docker build/run) from the proposed answer...Peper
+ you have "docker in docker" ('dind';), which is absolute overkill for the "simple requirement": "Installing specific version of NodeJS and NPM on Alpine docker image"Peper
please also point "the guy insingia" to: hub.docker.com/_/alpine/tags?page=1&name=3.17.2 (it has vulnerability reports) and should be upgraded (at least) to 3.17.3 (as of today)Peper
B
9

Here is my solution which is using unofficial node builds from https://nodejs.org/en/download

  1. Create Dockerfile, with desired alpine, node and npm versions In the example:
  • alpine v3.17.2
  • nodejs v18.16.0
  • npm v9.6.6
FROM alpine:3.17.2
ENV NODE_PACKAGE_URL  https://unofficial-builds.nodejs.org/download/release/v18.16.0/node-v18.16.0-linux-x64-musl.tar.gz

RUN apk add libstdc++
WORKDIR /opt
RUN wget $NODE_PACKAGE_URL
RUN mkdir -p /opt/nodejs
RUN tar -zxvf *.tar.gz --directory /opt/nodejs --strip-components=1
RUN rm *.tar.gz
RUN ln -s /opt/nodejs/bin/node /usr/local/bin/node
RUN ln -s /opt/nodejs/bin/npm /usr/local/bin/npm

# npm version coming with node is 9.5.1
# To install specific npm version, run the following command, or remove it to use the default npm version:
RUN npm install -g [email protected]

  1. Build a docker image
docker build -t node-18.16.0-npm-9.6.6-alpine-3.17.2 .
[+] Building 24.4s (15/15) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                                                           0.0s
 => => transferring dockerfile: 753B                                                                                                                                                                           0.0s
 => [internal] load .dockerignore                                                                                                                                                                              0.0s
 => => transferring context: 2B                                                                                                                                                                                0.0s
 => [internal] load metadata for docker.io/library/alpine:3.17.2                                                                                                                                               0.7s
 => [ 1/11] FROM docker.io/library/alpine:3.17.2@sha256:ff6bdca1701f3a8a67e328815ff2346b0e4067d32ec36b7992c1fdc001dc8517                                                                                       0.0s
 => CACHED [ 2/11] RUN apk add libstdc++                                                                                                                                                                       0.0s
 => CACHED [ 3/11] WORKDIR /opt                                                                                                                                                                                0.0s
 => CACHED [ 4/11] RUN wget https://unofficial-builds.nodejs.org/download/release/v18.16.0/node-v18.16.0-linux-x64-musl.tar.gz                                                                                 0.0s
 => CACHED [ 5/11] RUN mkdir -p /opt/nodejs                                                                                                                                                                    0.0s
 => [ 6/11] RUN tar -zxvf *.tar.gz --directory /opt/nodejs --strip-components=1                                                                                                                                4.2s
 => [ 7/11] RUN rm *.tar.gz                                                                                                                                                                                    0.3s
 => [ 8/11] RUN ls -l /opt/nodejs                                                                                                                                                                              0.6s
 => [ 9/11] RUN ln -s /opt/nodejs/bin/node /usr/local/bin/node                                                                                                                                                 0.2s
 => [10/11] RUN ln -s /opt/nodejs/bin/npm /usr/local/bin/npm                                                                                                                                                   0.2s
 => [11/11] RUN npm install -g [email protected]                                                                                                                                                                      17.1s
 => exporting to image                                                                                                                                                                                         1.0s
 => => exporting layers                                                                                                                                                                                        0.9s
 => => writing image sha256:e133d992089c2efd071b423fa093f81bf4a732ac06c1ec7dd6cb09cec894a9b3                                                                                                                   0.0s
 => => naming to docker.io/library/node-18.16.0-npm-9.6.6-alpine-3.17.2
  1. Run the container and check the installed versions
docker run -it node-18.16.0-npm-9.6.6-alpine-3.17.2 node --version
v18.16.0
docker run -it node-18.16.0-npm-9.6.6-alpine-3.17.2 npm --version
9.6.6
Bench answered 5/5, 2023 at 8:53 Comment(3)
Challenge is to install node 18.16.0 on alpine 3.17.2. Otherwise everyone knows that there is a prebuild image of every node version!Alidus
The answer has been updated with the required versions: Alpine 3.17.2, Node 18.16.0, and NPM 9.6.6. Note that all of these versions are subject to change.Bench
Clever solution! good job!Alidus
A
30

Use official versions

I don't know why you are using NVM.

According to your words. It doesn't matter how but you have to install a specific version of node on a specific version of alpine!

Just change NODE_VERSION and ALPINE_VERSION to what you need.

Here's my way using an alpine image not a node one:

ARG NODE_VERSION=18.16.0
ARG ALPINE_VERSION=3.17.2

FROM node:${NODE_VERSION}-alpine AS node

FROM alpine:${ALPINE_VERSION}

COPY --from=node /usr/lib /usr/lib
COPY --from=node /usr/local/lib /usr/local/lib
COPY --from=node /usr/local/include /usr/local/include
COPY --from=node /usr/local/bin /usr/local/bin

RUN node -v

RUN npm install -g yarn --force

RUN yarn -v

CMD ["node", "path/to/your/script.js"]

I removed your unnecessary package installations but you can add them if you need them!

e.g.: RUN apk add bash git helm openssh yq github-cli

e.g.: RUN rc-update add docker boot

Explanation

Add NODE_VERSION as ARG so you can use it in everywhere!

Copy binary files from official build of node:<version>-alpine to your version of alpine!

Simply install yarn using --force flag to avoid errors and DONE!!!!

CMD path/to/your/script.js is enough to run your long running JS. Don't use additional tools!

Compile the official versions

You can use the code provided by node it self from here. Just change the versions in the first two lines!

FROM alpine:3.17.2

ENV NODE_VERSION 18.16.0

RUN addgroup -g 1000 node \
    && adduser -u 1000 -G node -s /bin/sh -D node \
    && apk add --no-cache \
        libstdc++ \
    && apk add --no-cache --virtual .build-deps \
        curl \
    && ARCH= && alpineArch="$(apk --print-arch)" \
      && case "${alpineArch##*-}" in \
        x86_64) \
          ARCH='x64' \
          CHECKSUM="f3ad9443e8d9d53bfc00ec875181e9dc2ccf86205a50fce119e0610cdba8ccf1" \
          ;; \
        *) ;; \
      esac \
  && if [ -n "${CHECKSUM}" ]; then \
    set -eu; \
    curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \
    echo "$CHECKSUM  node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \
      && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
      && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \
  else \
    echo "Building from source" \
    # backup build
    && apk add --no-cache --virtual .build-deps-full \
        binutils-gold \
        g++ \
        gcc \
        gnupg \
        libgcc \
        linux-headers \
        make \
        python3 \
    # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150
    && export GNUPGHOME="$(mktemp -d)" \
    # gpg keys listed at https://github.com/nodejs/node#release-keys
    && for key in \
      4ED778F539E3634C779C87C6D7062848A1AB005C \
      141F07595B7B3FFE74309A937405533BE57C7D57 \
      74F12602B6F1C4E913FAA37AD3A89613643B6201 \
      DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \
      61FC681DFB92A079F1685E77973F295594EC4689 \
      8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
      C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
      890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \
      C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \
      108F52B48DB57BB0CC439B2997B01419BD92F80A \
    ; do \
      gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || \
      gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
    done \
    && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \
    && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
    && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
    && gpgconf --kill all \
    && rm -rf "$GNUPGHOME" \
    && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
    && tar -xf "node-v$NODE_VERSION.tar.xz" \
    && cd "node-v$NODE_VERSION" \
    && ./configure \
    && make -j$(getconf _NPROCESSORS_ONLN) V= \
    && make install \
    && apk del .build-deps-full \
    && cd .. \
    && rm -Rf "node-v$NODE_VERSION" \
    && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \
  fi \
  && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \
  && apk del .build-deps \
  # Run some smoke tests
  && node --version \
  && npm --version

ENV YARN_VERSION 1.22.19

RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \
  # use pre-existing gpg directory, see https://github.com/nodejs/docker-node/pull/1895#issuecomment-1550389150
  && export GNUPGHOME="$(mktemp -d)" \
  && for key in \
    6A010C5166006599AA17F08146C2130DFD2497F5 \
  ; do \
    gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || \
    gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
  done \
  && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
  && curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
  && gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
  && gpgconf --kill all \
  && rm -rf "$GNUPGHOME" \
  && mkdir -p /opt \
  && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
  && ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
  && ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
  && rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
  && apk del .build-deps-yarn \
  # smoke test
  && yarn --version

COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]

CMD [ "node" ]
Alidus answered 28/4, 2023 at 18:30 Comment(9)
Why are you installing docker/openrc within a Dockerfile? Why is "start on boot" processes needed in a Dockerfile? Why add bash when ash shell should work fine? None of these are needed to "run nodejs processes"Crown
@Crown This is installed by OP and I didn't remove it. Also there is a note! But you're right I should remove them.Alidus
In any case, the error in the question (127) is Docker's way of saying OOM, which could mean Docker Desktop on their Mac is memory constrained...Crown
@Crown no I built it on podman with 128gb of memory and got same error!! The files in NVM are broken!Alidus
What if you are from another image like FROM php:7.4-alpine then that doesn't workHolly
@Holly It is about node and alpine and it works on every version I tried. If there is a specific version that you tried and it doesn't work IDK actually, inform me!Alidus
Isnt there a way to just copy the required binaries/libraries instead of just copying everything in /usr/lib and /usr/local/..? While I like the approach, it copies/syncs way too many folders. How are we sure there aren't any other differences between those images?Damondamour
there is not much thing in those directories actually but Yes you can just copy a couple of files, I will write for you tommorowAlidus
@Damondamour Actually I checked in those directories! As I expected there is nothing but the files required by node! The image is still the most minified size!Alidus
B
9

Here is my solution which is using unofficial node builds from https://nodejs.org/en/download

  1. Create Dockerfile, with desired alpine, node and npm versions In the example:
  • alpine v3.17.2
  • nodejs v18.16.0
  • npm v9.6.6
FROM alpine:3.17.2
ENV NODE_PACKAGE_URL  https://unofficial-builds.nodejs.org/download/release/v18.16.0/node-v18.16.0-linux-x64-musl.tar.gz

RUN apk add libstdc++
WORKDIR /opt
RUN wget $NODE_PACKAGE_URL
RUN mkdir -p /opt/nodejs
RUN tar -zxvf *.tar.gz --directory /opt/nodejs --strip-components=1
RUN rm *.tar.gz
RUN ln -s /opt/nodejs/bin/node /usr/local/bin/node
RUN ln -s /opt/nodejs/bin/npm /usr/local/bin/npm

# npm version coming with node is 9.5.1
# To install specific npm version, run the following command, or remove it to use the default npm version:
RUN npm install -g [email protected]

  1. Build a docker image
docker build -t node-18.16.0-npm-9.6.6-alpine-3.17.2 .
[+] Building 24.4s (15/15) FINISHED
 => [internal] load build definition from Dockerfile                                                                                                                                                           0.0s
 => => transferring dockerfile: 753B                                                                                                                                                                           0.0s
 => [internal] load .dockerignore                                                                                                                                                                              0.0s
 => => transferring context: 2B                                                                                                                                                                                0.0s
 => [internal] load metadata for docker.io/library/alpine:3.17.2                                                                                                                                               0.7s
 => [ 1/11] FROM docker.io/library/alpine:3.17.2@sha256:ff6bdca1701f3a8a67e328815ff2346b0e4067d32ec36b7992c1fdc001dc8517                                                                                       0.0s
 => CACHED [ 2/11] RUN apk add libstdc++                                                                                                                                                                       0.0s
 => CACHED [ 3/11] WORKDIR /opt                                                                                                                                                                                0.0s
 => CACHED [ 4/11] RUN wget https://unofficial-builds.nodejs.org/download/release/v18.16.0/node-v18.16.0-linux-x64-musl.tar.gz                                                                                 0.0s
 => CACHED [ 5/11] RUN mkdir -p /opt/nodejs                                                                                                                                                                    0.0s
 => [ 6/11] RUN tar -zxvf *.tar.gz --directory /opt/nodejs --strip-components=1                                                                                                                                4.2s
 => [ 7/11] RUN rm *.tar.gz                                                                                                                                                                                    0.3s
 => [ 8/11] RUN ls -l /opt/nodejs                                                                                                                                                                              0.6s
 => [ 9/11] RUN ln -s /opt/nodejs/bin/node /usr/local/bin/node                                                                                                                                                 0.2s
 => [10/11] RUN ln -s /opt/nodejs/bin/npm /usr/local/bin/npm                                                                                                                                                   0.2s
 => [11/11] RUN npm install -g [email protected]                                                                                                                                                                      17.1s
 => exporting to image                                                                                                                                                                                         1.0s
 => => exporting layers                                                                                                                                                                                        0.9s
 => => writing image sha256:e133d992089c2efd071b423fa093f81bf4a732ac06c1ec7dd6cb09cec894a9b3                                                                                                                   0.0s
 => => naming to docker.io/library/node-18.16.0-npm-9.6.6-alpine-3.17.2
  1. Run the container and check the installed versions
docker run -it node-18.16.0-npm-9.6.6-alpine-3.17.2 node --version
v18.16.0
docker run -it node-18.16.0-npm-9.6.6-alpine-3.17.2 npm --version
9.6.6
Bench answered 5/5, 2023 at 8:53 Comment(3)
Challenge is to install node 18.16.0 on alpine 3.17.2. Otherwise everyone knows that there is a prebuild image of every node version!Alidus
The answer has been updated with the required versions: Alpine 3.17.2, Node 18.16.0, and NPM 9.6.6. Note that all of these versions are subject to change.Bench
Clever solution! good job!Alidus
C
3

Official node Dockerfiles are open source. You can start from one that is the closest to your requirements and tweak the minor versions for your needs.

You need alpine:3.17.2 and NODE_VERSION 18.16.0 so this alpine-3.17.0 with node-18.16.0 is a good Dockerfile candidate to start with.

Then adjust the versions and remove yarn if you don't need it(luckily the node-18.16.0 is an exact match with what you need, so the only thing left is to bump the alpine starting version):

# Original source: https://github.com/nodejs/docker-node/blob/4c95f887f7863eccc17d66729cd24ecc230209a2/18/alpine3.17/Dockerfile
# Your requirements:
# alpine:3.17.2
# NODE_VERSION 18.16.0


# EDIT: this should satisfy the requirement of person with more stars on the shoulder:
FROM alpine:3.17.2

# EDIT: Everything else is code from official image:
ENV NODE_VERSION 18.16.0

RUN addgroup -g 1000 node \
    && adduser -u 1000 -G node -s /bin/sh -D node \
    && apk add --no-cache \
        libstdc++ \
    && apk add --no-cache --virtual .build-deps \
        curl \
    && ARCH= && alpineArch="$(apk --print-arch)" \
      && case "${alpineArch##*-}" in \
        x86_64) \
          ARCH='x64' \
          CHECKSUM="d093ef223708a6702db1dc591911f3b23481cb55a337df3adf80b6effaba90b2" \
          ;; \
        *) ;; \
      esac \
  && if [ -n "${CHECKSUM}" ]; then \
    set -eu; \
    curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz"; \
    echo "$CHECKSUM  node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" | sha256sum -c - \
      && tar -xJf "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
      && ln -s /usr/local/bin/node /usr/local/bin/nodejs; \
  else \
    echo "Building from source" \
    # backup build
    && apk add --no-cache --virtual .build-deps-full \
        binutils-gold \
        g++ \
        gcc \
        gnupg \
        libgcc \
        linux-headers \
        make \
        python3 \
    # gpg keys listed at https://github.com/nodejs/node#release-keys
    && for key in \
      4ED778F539E3634C779C87C6D7062848A1AB005C \
      141F07595B7B3FFE74309A937405533BE57C7D57 \
      74F12602B6F1C4E913FAA37AD3A89613643B6201 \
      DD792F5973C6DE52C432CBDAC77ABFA00DDBF2B7 \
      61FC681DFB92A079F1685E77973F295594EC4689 \
      8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
      C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
      890C08DB8579162FEE0DF9DB8BEAB4DFCF555EF4 \
      C82FA3AE1CBEDC6BE46B9360C43CEC45C17AB93C \
      108F52B48DB57BB0CC439B2997B01419BD92F80A \
    ; do \
      gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys "$key" || \
      gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key" ; \
    done \
    && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.tar.xz" \
    && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
    && gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
    && grep " node-v$NODE_VERSION.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
    && tar -xf "node-v$NODE_VERSION.tar.xz" \
    && cd "node-v$NODE_VERSION" \
    && ./configure \
    && make -j$(getconf _NPROCESSORS_ONLN) V= \
    && make install \
    && apk del .build-deps-full \
    && cd .. \
    && rm -Rf "node-v$NODE_VERSION" \
    && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \
  fi \
  && rm -f "node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \
  && apk del .build-deps \
  # smoke tests
  && node --version \
  && which node \
  && npm --version \
  && which npm

# Replace the entrypoint you need after confirming that prerequisites are OK
ENTRYPOINT ["sh"]

Note the last 4 commands that print the node and npm versions.
You may also run the container to do the same:

On host:

docker build -t alpine-node:3.17.2-18.16.0 .
docker run -it alpine-node:3.17.2-18.16.0

In container:

node --version && which node && npm --version && which node

Output:

v18.16.0
/usr/local/bin/node
9.5.1
/usr/local/bin/node
/ #
Claxton answered 29/4, 2023 at 7:2 Comment(5)
It's a complex solution to install on clean alpine but it comes more cleaner and lighter I think. Good perspective though! Liked your answerAlidus
@Alidus 1. May I ask where's the complexity in changing one digit? Perhaps you missed the whole point of my answer. 2. It comes as clean as official docker image, hence it's the same source code, except for the alpine patch version. 3. As for liking/disliking, SO recommends using up or down-votes, rather than antithetical comments :). 4. A multi stage build is a clever idea which I assume is leading to a very similar result.Claxton
1. Complexity is in the source code and future debugs as version changes! 2. I voted up in the first place days ago 3. Just thought to make a comment about the final size and dirty files in the comments and know you opinion.Alidus
@Alidus feedback: your answer it's clever, the Dockerfile has less lines and seems easier to maintain. I believe my approach deviates less from the official image and btw, we're on the same page with the "use official images" statement. I'm just more comfortable "forking" the official Dockerfile and tweaking a minor version, rather than having to worry about which files must to copied from one stage to another. In the end is just a matter of taste. Those who come across this question will find at least 2 answers to choose from and will eventually pick what fits their taste/needs, not ours :)Claxton
you're right about same page and about the image structure. That was my question actually and your answer to that seems reasonable. Thanks by the way.Alidus
I
0

This is my solution, add repository to /ect/apk/repositories. You should be able to find the corresponding nodejs version you want in this http://dl-cdn.alpinelinux.org/alpine. And this is my

Dockerfile

FROM alpine:3.17
RUN apk add --no-cache bash
RUN echo "@personal http://dl-cdn.alpinelinux.org/alpine/v3.15/main" >> /etc/apk/repositories
RUN apk add nodejs@personal npm@personal
RUN node --version
RUN npm --version
CMD ["bash"]

build docker image

$ docker build --progress=plain -t alpine-test . --no-cache

result

...
#8 [5/6] RUN node --version
#8 0.264 v16.20.1
#8 DONE 0.3s

#9 [6/6] RUN npm --version
#9 0.443 8.1.3
#9 DONE 0.5s
...

ref this Alpine_Package_Keeper

Indisposition answered 25/8, 2023 at 6:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.