Files
pnpm/pnpr/docker/README.md
Zoltan Kochan 430d892741 feat(pnpr)!: serve every ecosystem under its own prefix (#17087)
pnpr served npm at the server root when npm was the only configured
ecosystem and moved it under /npm/ as soon as a second ecosystem was
added. Adding an ecosystem therefore broke every .npmrc registry URL,
every tarball URL already written into a lockfile, named-registry URLs,
and OIDC workload publish paths, and /npm meant the package `npm` on one
server and the ecosystem prefix on another. This settles section A1 of
pnpm/tasks#131: every ecosystem is always prefixed.

- Ecosystem::base_path is now independent of the configuration. The
  per-configuration Registries::base_path and is_only_ecosystem are gone,
  and the routes, the resolver's tarball URLs, OIDC workload paths and
  pnpr's own-origin route classification all use it.
- The default image registry still answers at /v2/ on the host root; an
  image client cannot be pointed at a prefix. The registry directory keeps
  its `prefixed` and `namedPrefixed` flags for the web UI.
- The read-only token allowlist matched the npm audit endpoints at the
  root only, so read-only tokens were already refused for audits on
  multi-ecosystem servers. It now matches them under the npm prefix.
- /metrics no longer switches between Prometheus metrics and the npm
  package `metrics` on the Accept header; the package is /npm/metrics.
- The pnpm v11 and v12 test harnesses, the registry-mock crate and the
  integrated benchmark address the fixture registry at /npm/ and keep the
  server origin for the pnpr protocol endpoints. The benchmark asks each
  revision mock's registry directory whether npm is prefixed, so it can
  still compare against a pnpr revision from before this change.
2026-10-18 16:55:55 +02:00

2.4 KiB

pnpr Docker image

Official image for pnpr, the pnpm-compatible npm registry server, published to GitHub Container Registry.

ghcr.io/pnpm/pnpr

Based on debian:stable-slim with the standalone pnpr binary (static musl build, the same artifact published to npm). The container runs as a non-root pnpr user and listens on port 7677.

Tags

Tag Meaning
<version> Exact, immutable (e.g. 0.2.3). Includes prereleases.
latest Most recent stable release. Not updated for prereleases.

Supported platforms

linux/amd64, linux/arm64.

Usage

docker run --rm -p 7677:7677 \
  -v pnpr-storage:/pnpr/storage \
  ghcr.io/pnpm/pnpr:latest

The default command binds to 0.0.0.0:7677 and stores published packages in /pnpr/storage and the disposable upstream mirror in /pnpr/cache (both declared as volumes). To use a custom config, mount it and point pnpr at it:

docker run --rm -p 7677:7677 \
  -v "$PWD/config.yaml:/pnpr/config.yaml:ro" \
  -v pnpr-storage:/pnpr/storage \
  ghcr.io/pnpm/pnpr:latest --listen 0.0.0.0:7677 --config /pnpr/config.yaml

Then point pnpm at it:

pnpm config set registry http://localhost:7677/npm/

Build locally

The build context expects the binary for each target architecture, staged as pnpr-amd64 / pnpr-arm64. Build one with cross (or cargo for the host arch) and drop it in:

The build verifies the binary against a SHA256 checksum before trusting it, so pass the checksum for the architecture you're building:

VERSION=0.2.3
cross build -p pnpr --bin pnpr --release --target x86_64-unknown-linux-musl
cp target/x86_64-unknown-linux-musl/release/pnpr pnpr/docker/pnpr-amd64
docker buildx build \
  --build-arg PNPR_VERSION=${VERSION} \
  --build-arg PNPR_SHA256_AMD64=$(shasum -a 256 pnpr/docker/pnpr-amd64 | awk '{print $1}') \
  --platform linux/amd64 \
  --load \
  -t pnpr-test ./pnpr/docker
docker run --rm pnpr-test --version

Release

Images are built and pushed by the docker-pnpr job in .github/workflows/release.yml, which runs after the npm packages are published. The build verifies each staged binary against the SHA256 checksum pinned by the release job and fails if pnpr --version in the image doesn't match the PNPR_VERSION build-arg.