Files
pnpm/docker/Dockerfile
Zoltan Kochan 9ae1ca7253 feat: publish base docker image to GHCR (#11302)
* feat: publish base docker image to GHCR

Adds a Dockerfile (debian:stable-slim + pnpm standalone binary) and a
release-triggered workflow that builds multi-arch images and pushes to
ghcr.io/pnpm/pnpm. Users who need Node.js can install it inside the
container via `pnpm runtime set node <version>`.

Refs #11300

* docs: add docker/README.md

* chore(cspell): add buildx to dictionary

* docs: mention devEngines.runtime as alternative to pnpm runtime set

* fix(docker): pin base image, verify tarball sha256, harden download

- Pin `debian:stable-slim` to a digest for reproducibility.
- Compute pnpm tarball SHA256 in the workflow and verify it inside the
  build, detecting tampered artifacts regardless of what `pnpm --version`
  reports.
- Download the tarball to disk with `--retry` instead of `curl | tar`
  for resilience under multi-arch QEMU builds.
- README: use `--load` so the local test image is available to `docker run`.

* chore(cspell): sort dictionary additions

* fix(docker): address Copilot review feedback

- Include $PNPM_HOME/bin on PATH so pnpm-installed globals (node, etc.)
  are discoverable, and make $PNPM_HOME writable for non-root users.
- Document that `pnpm runtime set node` needs `-g` to install globally.
- Pass workflow inputs via env: instead of inlining GitHub expressions
  into shell, and validate the version string before use.

* fix(docker): install libatomic1 for pnpm standalone binary

The pnpm linux standalone binary dynamically links against
libatomic.so.1, which is not present in debian:stable-slim by
default. Without it, `pnpm --version` fails during the build with:

  pnpm: error while loading shared libraries: libatomic.so.1:
  cannot open shared object file: No such file or directory

Caught by local build testing.
2026-04-19 18:59:24 +02:00

45 lines
1.7 KiB
Docker

# syntax=docker/dockerfile:1.7
# Refresh periodically: resolve with
# docker buildx imagetools inspect debian:stable-slim --format '{{.Manifest.Digest}}'
FROM debian:stable-slim@sha256:e51bfcd2226c480a5416730e0fa2c40df28b0da5ff562fc465202feeef2f1116
ARG PNPM_VERSION
ARG PNPM_SHA256_AMD64
ARG PNPM_SHA256_ARM64
ARG TARGETARCH
ENV PNPM_HOME=/pnpm
ENV PATH=$PNPM_HOME/bin:$PATH
RUN set -eu; \
test -n "$PNPM_VERSION"; \
apt-get update; \
apt-get install -y --no-install-recommends ca-certificates curl libatomic1; \
rm -rf /var/lib/apt/lists/*; \
case "$TARGETARCH" in \
amd64) arch=x64; expected_sha="$PNPM_SHA256_AMD64" ;; \
arm64) arch=arm64; expected_sha="$PNPM_SHA256_ARM64" ;; \
*) echo "unsupported architecture: $TARGETARCH" >&2; exit 1 ;; \
esac; \
test -n "$expected_sha" || { echo "missing PNPM_SHA256_* build-arg for $TARGETARCH" >&2; exit 1; }; \
mkdir -p /opt/pnpm "$PNPM_HOME/bin"; \
chmod -R a+rwX "$PNPM_HOME"; \
curl -fsSL --retry 3 --retry-delay 2 -o /tmp/pnpm.tgz \
"https://github.com/pnpm/pnpm/releases/download/v${PNPM_VERSION}/pnpm-linux-${arch}.tar.gz"; \
actual_sha="$(sha256sum /tmp/pnpm.tgz | awk '{print $1}')"; \
test "$actual_sha" = "$expected_sha" || { \
echo "sha256 mismatch for pnpm-linux-${arch}.tar.gz: expected $expected_sha, got $actual_sha" >&2; \
exit 1; \
}; \
tar -xzf /tmp/pnpm.tgz -C /opt/pnpm; \
rm /tmp/pnpm.tgz; \
ln -s /opt/pnpm/pnpm /usr/local/bin/pnpm; \
installed="$(pnpm --version)"; \
test "$installed" = "$PNPM_VERSION" || { \
echo "pnpm version mismatch: expected $PNPM_VERSION, got $installed" >&2; \
exit 1; \
}
WORKDIR /app