Node.js with V8 pointer compression, on Alpine, for amd64 and arm64
1.0K
Node.js built with V8 pointer compression, on Alpine, for linux/amd64 and linux/arm64.
A drop-in replacement for node:alpine that uses less memory.
docker run --rm smeagolworms4/node-pointer-compression:24-alpine -p process.config.variables.v8_enable_pointer_compression
1
On a 64-bit machine every reference between JavaScript objects takes 8 bytes. With pointer compression, V8 keeps the whole heap inside one 4 GB region and stores each reference as a 4-byte offset, so the JavaScript heap shrinks. Chrome ships V8 this way; the official Node.js binaries do not.
The Node.js project publishes an unofficial pointer-compression binary for glibc on x64 only. Nothing exists for arm64, nor for Alpine. This repository builds both architectures from the official sources and publishes them every time Node.js releases.
Measured on KomgaJS, a media server, with the same workload on the stock binary and on a pointer-compression build:
| Stock Node.js | Pointer compression | |
|---|---|---|
| Resident memory after a library scan, x64 desktop | 247 MB | 220 MB |
| Resident memory in use, arm64 Raspberry Pi, 6,500 books | 222 MB | 185 MB |
| Scan time, API latency, throughput | — | no measurable difference |
Only the JavaScript heap shrinks: native memory (buffers, SQLite, image libraries) is untouched, so the gain depends on how much of your process is JavaScript objects.
smeagolworms4/node-pointer-compression on Docker Hub, tagged like the official image:
| Tag | Content |
|---|---|
24.21.0-alpine, 24-alpine, lts-alpine, current-alpine, alpine, latest | Node.js, npm, and the headers needed to build native addons |
24.21.0-alpine-slim, 24-alpine-slim, lts-alpine-slim, current-alpine-slim, alpine-slim, slim | the node binary only, for final images that install nothing |
lts is the newest LTS line, current the newest line; alpine, latest and slim follow lts.linux/amd64 and linux/arm64.node:alpine: node user (uid 1000), /usr/local prefix, same entrypoint.corepack enable on the lines that still ship Corepack, or npm install -g yarn.Typical use, building with the full image and running on the slim one:
FROM smeagolworms4/node-pointer-compression:24-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
FROM smeagolworms4/node-pointer-compression:24-alpine-slim
WORKDIR /app
COPY --from=build /app .
USER node
CMD ["server.js"]
--max-old-space-size above that has no effect. Buffers and other native memory do not count.better-sqlite3 is loaded in the tests of every build). An addon that uses the V8 API directly
must be compiled against this build: the headers are in the full image, under /usr/local/include/node.node:alpine: prebuilt glibc binaries do not load.--experimental-enable-pointer-compression),
and these binaries do not go through the Node.js release test suite. Each image is only
smoke-tested here (see below): run your own tests on it before relying on it.Dockerfile:
the source-build path of the official node:alpine Dockerfile, with one more ./configure flag.
The source tarball is checked against the signed SHASUMS256.txt of the release, with the
Node.js release keyring.tools/versions.mjs:
reads the Node.js release schedule and the list of releases,
keeps the latest version of every maintained line, drops the ones already on Docker Hub..github/workflows/:
one workflow per architecture (build-amd64.yml, build-arm64.yml), each run every day on a
native runner, with no emulation. A missing version is compiled, then tested before anything is
pushed: test/smoke.mjs
checks that pointer compression is on, that objects really take 4-byte references, and that
crypto, zlib, ICU and WebAssembly work; a Node-API addon is installed and loaded. The image is
pushed as <version>-alpine-<arch>; a version gets its multi-architecture tags once both
architectures are there, and this README is copied to Docker Hub.Build one yourself:
docker build --build-arg NODE_VERSION=24.21.0 --target full -t node-pc:24.21.0-alpine .
docker build --build-arg NODE_VERSION=24.21.0 --target slim -t node-pc:24.21.0-alpine-slim .
docker run --rm -v "$PWD/test:/test:ro" node-pc:24.21.0-alpine node /test/smoke.mjs 24.21.0
Compiling Node.js takes a while: count in hours on a 4-core machine.
--build-arg JOBS=4 limits the parallelism, --build-arg ALPINE_VERSION=3.23 picks another base,
--build-arg NODE_CONFIGURE_FLAGS="--with-intl=small-icu" passes more flags to ./configure.
MIT for the files of this repository. Node.js and its dependencies keep their own licences. The entrypoint script comes from docker-node (MIT).
Content type
Image
Digest
sha256:57981486c…
Size
51.1 MB
Last updated
2 days ago
docker pull smeagolworms4/node-pointer-compression