Node.js on Alpine Linux inside Docker: update to latest minor version

I want to create a Docker image which does two simple things:

  • Pull node:14-alpine
  • Update to the latest minor Node.js version

I've read that both n and nvm have their issues on Alpine Linux. So, what would be the best way to proceed?

(Background: At the time of writing, node:14-alpine is 14.17.1, whereas the latest minor Node.js version of 14 is 14.17.3. So, it makes sense to fetch the latest version and not wait for the official release.)


At the time of writing 14.17.3 was already released. So I guess the simple answer is waiting a few days is the most practial thing you can do. It might even possible that you had to re-pull the node:14-alpine to get the updated image.

But if you really want to see what needs to be done, you can look into the Dockerfile of every official docker image. For your node:14-alpine image it's located here: https://github.com/nodejs/docker-node/blob/main/14/alpine3.14/Dockerfile

And from line 19 onwards you see the following:

ENV NODE_VERSION 14.17.3 # line 3
# snip
    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;

that's what they did to install the binary distribution of node (albeit from line 26 onwards you can see to compile all yourself). Verifying the sha256 checksum is optional, though.

So you can do the same and overwrite the node version inside the alpine container like so.

Edit: If you don't like hardcoding the version, you can automate it with curl and jq (which needs to be installed):

# Install jq and curl dependencies
apk add --no-cache jq curl
# Get major.minor version (that is v14.xx for node:14-alpine)
export NODE_MAJOR_MINOR_VERSION=$(node --version | cut -d. -f1,2)
# Dynamically receive the newest version for the major version of this image
export DOWNLOAD_VERSION=$(curl -fsSL --compressed https://unofficial-builds.nodejs.org/download/release/index.json | jq --raw-output ".[]|select(.version | startswith(\"$NODE_MAJOR_MINOR_VERSION\"))|.version" | head -1)
# Download the suitable tarball
curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/$DOWNLOAD_VERSION/node-$DOWNLOAD_VERSION-linux-x64-musl.tar.xz"
# Uncompress the tarball
tar -xJf "node-$DOWNLOAD_VERSION-linux-x64-musl.tar.xz" -C /usr/local --strip-components=1 --no-same-owner
# Overwrite symlink node -> nodejs
ln -sf /usr/local/bin/node /usr/local/bin/nodejs