Adds `<version>-alpine`, `<major>-alpine`, and `alpine` tags built from docker/Dockerfile.alpine with the musl release tarball. Alpine users can use the image as a base or copy /opt/pnpm into `node:*-alpine` without fetching the installer from get.pnpm.io, which was returning 403 to bursts of concurrent CI jobs. The download, checksum, and version check move into docker/install-pnpm.sh, shared by both Dockerfiles. The Alpine image also installs libstdc++ and libgcc, which the musl Node.js builds installed by `pnpm runtime` need. The Alpine build runs only for releases that ship musl tarballs for both x64 and arm64, so v11 and v10 releases skip it. Every release used to publish the `latest` and `<major>` tags, so a v11 maintenance release moved `latest` back to v11. The builds now push only the exact version tags. A final step lists the stable releases and, with `docker buildx imagetools create`, points `<major>` at the highest version in that major and `latest` at the highest version overall. The Alpine tags follow the same rule. Deciding after the builds sees every release of a burst, since lines are published seconds apart. A concurrency group was rejected because GitHub cancels a pending run when a third one queues. The selection lives in .github/scripts/docker-image-tags.sh with a test run by CI, and fails on an empty release list. The v12 CI docs now run the Bitbucket Pipelines and GitLab CI examples in `ghcr.io/pnpm/pnpm:12` instead of downloading the installer, and recommend the image for CI that runs jobs in containers. CircleCI keeps the installer because its checkout step needs git and ssh. The CI examples that still use the standalone script fall back to the latest pnpm/get.pnpm.io installer release when get.pnpm.io fails. They run the script only after a download succeeds. Related to pnpm/pnpm#16973.
pnpm base Docker image
Official base image for pnpm, published to GitHub Container Registry.
ghcr.io/pnpm/pnpm
Based on debian:stable-slim with the pnpm standalone binary. Node.js is not bundled — install the version you need inside your own image with pnpm runtime set node <version> -g (the -g flag makes node available on PATH for subsequent layers and at runtime).
Tags
| Tag | Meaning |
|---|---|
<version> |
Exact, immutable (e.g. 11.0.0). Includes prereleases. |
<major> |
Tracks the latest stable release within that major (e.g. 11). |
latest |
Highest stable pnpm version. Not updated for prereleases. |
<version>-alpine, <major>-alpine, alpine |
The same, based on Alpine Linux with the musl build of pnpm. |
Alpine variant
The -alpine tags are based on alpine:3.24 and contain the musl build of pnpm in /opt/pnpm. They are published for pnpm 12 and later.
To add pnpm to an existing image, such as node:<version>-alpine, copy the whole directory. The dist directory next to the binary holds the bundled node-gyp:
FROM node:24-alpine
COPY --from=ghcr.io/pnpm/pnpm:12-alpine /opt/pnpm /opt/pnpm
RUN ln -s /opt/pnpm/pnpm /usr/local/bin/pnpm
Supported platforms
linux/amd64, linux/arm64.
Usage
Install Node.js explicitly with pnpm runtime set:
FROM ghcr.io/pnpm/pnpm:latest
RUN pnpm runtime set node 22 -g
WORKDIR /app
COPY . .
RUN pnpm install --frozen-lockfile
CMD ["node", "index.js"]
Or let pnpm install Node.js from devEngines.runtime in your package.json:
{
"devEngines": {
"runtime": {
"name": "node",
"version": "22.x",
"onFail": "download"
}
}
}
FROM ghcr.io/pnpm/pnpm:latest
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
CMD ["pnpm", "start"]
Build locally
VERSION=11.0.0-rc.2
SHA=$(curl -fsSL "https://github.com/pnpm/pnpm/releases/download/v${VERSION}/pnpm-linux-x64.tar.gz" \
| sha256sum | awk '{print $1}')
docker buildx build \
--build-arg PNPM_VERSION=${VERSION} \
--build-arg PNPM_SHA256_AMD64=${SHA} \
--platform linux/amd64 \
--load \
-t pnpm-test ./docker
docker run --rm pnpm-test pnpm --version
For the Alpine image, checksum pnpm-linux-x64-musl.tar.gz instead and pass -f docker/Dockerfile.alpine.
Release
Images are built and pushed by .github/workflows/docker.yml on release: published, or manually via workflow_dispatch. The build fails if pnpm --version in the image doesn't match the PNPM_VERSION build-arg.