Minimal Dev Container image for Node.js with pnpm: Debian, verified upstreams, SLSA provenance
6.3K
Mirror. This Docker Hub repository mirrors
ghcr.io/bare-devcontainer/pnpm, under the same tags and with the same digests. GitHub Container Registry receives every build first and applies no pull rate limit, so preferghcr.io/bare-devcontainer/pnpmunless your environment requires Docker Hub, where the image isdocker.io/baredevcontainer/pnpm.This page is rendered from the image's README in bare-devcontainer/images. That is the repository "this repository" refers to below.
Dev container image with pnpm installed, built on the debian base image. pnpm installs the Node.js version the project asks for, so the runtime is chosen by the project rather than baked into the image.
Like every image in this repository, it is minimal, built only from upstreams verified at build
time, and published with SLSA provenance, a GitHub artifact attestation, and an SBOM; it runs as
the non-root user dev. Why these images explains the
reasoning, and Verifying the image below shows how to check a build.
ghcr.io/bare-devcontainer/pnpm:<tag>
Reference it from .devcontainer/devcontainer.json, pinning the digest as well as the tag:
{
"image": "ghcr.io/bare-devcontainer/pnpm:12@sha256:<digest>"
}
A ready-to-use Dev Container template for this image is available at bare-devcontainer/templates. It provides the recommended configuration for this image, including security hardening and volume mounts that persist cache directories for faster rebuilds.
| Tags | Debian variant |
|---|---|
12.7.0-trixie, 12-trixie, 12.7.0, 12, trixie | trixie |
12.7.0-bookworm, 12-bookworm, bookworm | bookworm |
Tags are also published with a date suffix on each build (e.g., 12.7.0-trixie-<YYYYMMDD>).
The version in these tags is the version of pnpm itself, not of any Node.js runtime.
Everything from the debian base image, plus:
pnpm), with bash completions installedpnpm is installed under /opt/pnpm with a /usr/local/bin/pnpm symlink, the layout of pnpm's
own ghcr.io/pnpm/pnpm image. Under a Dev Container
client, PNPM_HOME is ~/.local/share/pnpm and its bin directory is on PATH, so runtimes
and globally installed packages resolve without further setup. Running the image without one
(docker run, a CI job's container:) declares neither, so a global install needs both set
first.
devEngines.runtime, so the version in use is
the one the project asks for. See Working with runtimes below.npm, npx, or Corepack. pnpm covers those workflows, and installing a Node.js runtime
with pnpm deliberately leaves the bundled npm unextracted. Run pnpm add -g npm if a project
needs it. For a project whose package manager is not pnpm, use the node image instead.Declare the runtime in the project's package.json and pnpm installs it on first use:
{
"devEngines": {
"runtime": { "name": "node", "version": "^24.0.0", "onFail": "download" }
}
}
Inside that project a bare node runs the pinned version, because pnpm's global node is a shim
that dispatches to what the project asks for. Outside any project it runs the globally installed
version, which is set with pnpm runtime:
pnpm runtime set node lts -g
To install the project's runtime and dependencies when the container is created rather than on
first use, run pnpm install from a postCreateCommand.
Two directories are worth persisting across container rebuilds as volumes:
~/.local/share/pnpm — the store, the managed runtimes, and the bins of globally installed
packages. All of it is re-downloaded on every rebuild unless this directory survives.~/.cache/pnpm — the metadata cache.pnpm is downloaded from GitHub Releases, the same archive
pnpm's own container image installs, and verified against a checksum committed to this repository
(pnpm/pnpm-amd64.sha256, pnpm/pnpm-arm64.sha256).
pnpm publishes neither a checksum nor a detached signature, so that checksum is not fetched from
upstream — it is derived here, and only from an archive whose origin has been established.
.github/workflows/update-material.yml runs pnpm/checksum.sh whenever the pinned version changes,
and the script records a digest only after gh attestation verify has confirmed that the archive's
build provenance was signed
by pnpm's release workflow at that version's tag. The resulting checksum is committed and reviewed
like any other change, so what the image build trusts is a digest this repository accepted, rather
than one the release host served alongside the archive.
Note that this covers the pnpm binary only. Runtimes and packages that pnpm installs at runtime are fetched from their own upstreams under pnpm's own verification, outside this image's build pipeline.
Every build is published with SLSA provenance, a GitHub artifact attestation, and an SBOM. The attestation confirms that an image was built by the release workflow of this repository and has not been altered since:
gh attestation verify oci://ghcr.io/bare-devcontainer/pnpm:<tag>@sha256:<digest> \
--owner bare-devcontainer
The Docker Hub mirror carries the same digests, so the same command verifies an image pulled
from docker.io/baredevcontainer/pnpm.
Verifying Published Images covers inspecting the
provenance and the SBOM as well.
Content type
Image
Digest
sha256:5e796fce8…
Size
247.6 MB
Last updated
1 day ago
docker pull baredevcontainer/pnpm:12.7.0-bookworm