@host.today/ht-docker-node
multiarch docker base images | [host.today](https://host.today)
readme.md for @host.today/ht-docker-node
🐳 ht-docker-node
Production-ready Docker images for Node.js with NVM built in, multi-arch support, and modern runtimes (Bun, Deno). Every image ships with tini as PID 1 and full NVM integration — switch Node versions on the fly, no sourcing required.
Multi-arch • Alpine & Ubuntu • NVM built-in • Bun, Deno & pnpm • tini init • CI/CD optimized
Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.
🚀 Quick Start
# Pull and run the full-featured Ubuntu image
docker pull code.foss.global/host.today/ht-docker-node:latest
docker run -it code.foss.global/host.today/ht-docker-node:latest
# Or go lean with Alpine (~200 MB vs ~900 MB)
docker pull code.foss.global/host.today/ht-docker-node:alpine-node
docker run -it code.foss.global/host.today/ht-docker-node:alpine-node
NVM is ready the moment you enter the container — no manual sourcing, no .bashrc hacks:
$ nvm install 22
$ nvm use 22
$ node -v # v22.x.x ✅
📦 Available Images
Ubuntu-Based (Full-Featured)
Built on Ubuntu 24.04. Maximum compatibility, all build tools included, plus Chromium for Puppeteer/Playwright, and MongoDB 8.0.
| Tag | Description | Key Contents |
|---|---|---|
:latest |
Kitchen-sink Node.js image | Node LTS + NVM + pnpm + Bun + Deno + Chromium + MongoDB 8.0 |
:lts |
Alias of :latest |
Same — explicit LTS naming for clarity |
:szci |
CI/CD workhorse | :latest + @ship.zone/szci preinstalled |
:fossglobal_preinstalled_<ver> |
Preloaded tooling image | :szci + tsrun, tstest, tapbundle, smartfile, and more |
Alpine-Based (Lightweight & Multi-Arch) ⚡
40–75 % smaller than Ubuntu. Native performance on both amd64 and arm64 (Apple Silicon, Graviton, Ampere).
| Tag | Description | Size | Architectures |
|---|---|---|---|
:alpine-node |
Node.js LTS + NVM + pnpm | ~200 MB | amd64, arm64 |
:alpine-bun |
Node.js LTS + NVM + Bun | ~150 MB | amd64, arm64 |
:alpine-deno |
Node.js LTS + NVM + Deno | ~180 MB | amd64, arm64 |
:alpine-szci |
Alpine Node + szci + build tools | ~250 MB | amd64, arm64 |
💡 Docker automatically pulls the right arch for your platform. Build on a Mac, deploy on an ARM server — same tag, native speed everywhere.
Note: The Deno Alpine image uses
alpine:edgeto get the official musl-compiled Deno from the community repository.
What every image includes
| Feature | Detail |
|---|---|
| tini | PID 1 init — proper signal forwarding & zombie reaping |
| NVM | v0.40.1 — works in RUN, docker exec, CI scripts, interactive shells |
| Node.js | LTS v24.13.0 (default, switchable) |
| docker-entrypoint.sh | Loads NVM at runtime so docker run … bash -c "nvm use 22" just works |
💡 Key Features
🔄 NVM — Zero-Config Node Version Management
NVM is pre-wired into every shell context. No manual sourcing required in any of these scenarios:
Dockerfile RUN commands (via the bash-with-nvm SHELL wrapper):
FROM code.foss.global/host.today/ht-docker-node:latest
# Works directly — no sourcing needed!
RUN nvm install 22 && nvm use 22 && npm ci
RUN nvm alias default 22 # persists for later RUN steps
CI/CD scripts (via BASH_ENV=/etc/bash.bashrc):
# Gitea / GitLab CI
test:
image: code.foss.global/host.today/ht-docker-node:latest
script:
- nvm install 22 && nvm use 22
- pnpm ci && pnpm test
Interactive shells and docker exec:
docker exec -it mycontainer bash
$ nvm ls # lists installed versions
$ nvm install 20 # installs Node 20
$ nvm use 20 # switches immediately
⚠️ Note on version persistence across RUN steps: Each Dockerfile
RUNstarts a new shell. Usenvm alias default <version>to persist your choice, or chain commands in a singleRUN.
🛡️ tini — Proper Init for Containers
All images use tini as PID 1:
tini → docker-entrypoint.sh → your command
This means:
- ✅ Signals (SIGTERM, SIGINT) are forwarded correctly to your app
- ✅ Zombie processes are reaped automatically
- ✅ Clean container shutdown — no orphaned processes
🌐 Chromium (Ubuntu :latest only)
Puppeteer and Playwright work out of the box:
const browser = await puppeteer.launch(); // uses /usr/bin/chromium-browser
Environment variables PUPPETEER_EXECUTABLE_PATH and CHROME_BIN are pre-set. Multi-arch compatible (amd64 + arm64).
🏔️ Alpine — Production Optimized
FROM code.foss.global/host.today/ht-docker-node:alpine-node
RUN nvm install 22 && nvm use 22
RUN pnpm install && pnpm build
# Result: ~200 MB image
Why Alpine?
- ✅ 60–75 % smaller → Faster pulls, faster deploys
- ✅ Reduced attack surface → Fewer packages = fewer CVEs
- ✅ Native musl builds → No glibc compatibility layer
- ✅ Multi-arch → Same tag works on x64 and ARM64
🛠️ Usage Examples
Basic Node.js App
FROM code.foss.global/host.today/ht-docker-node:alpine-node
WORKDIR /app
COPY package*.json ./
RUN pnpm install
COPY . .
RUN pnpm build
EXPOSE 3000
CMD ["node", "dist/index.js"]
Multi-Version Testing
FROM code.foss.global/host.today/ht-docker-node:latest
WORKDIR /app
COPY package*.json ./
RUN nvm install 20 && nvm use 20 && npm ci && npm test
RUN nvm install 22 && nvm use 22 && npm ci && npm test
# Ship with Node 22
RUN nvm alias default 22 && npm run build
Deno Application
FROM code.foss.global/host.today/ht-docker-node:alpine-deno
WORKDIR /app
COPY . .
# Deno and Node.js are both available
CMD ["deno", "run", "--allow-net", "main.ts"]
Bun for Ultra-Fast Installs
FROM code.foss.global/host.today/ht-docker-node:alpine-bun
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install
COPY . .
RUN bun run build
CMD ["bun", "run", "start"]
TypeScript Multi-Stage Build
# Build stage
FROM code.foss.global/host.today/ht-docker-node:alpine-node AS builder
WORKDIR /app
COPY package*.json ./
RUN pnpm install
COPY tsconfig.json ./
COPY src ./src
RUN pnpm build
# Production stage — only runtime deps
FROM code.foss.global/host.today/ht-docker-node:alpine-node
WORKDIR /app
COPY package*.json ./
RUN pnpm install --prod
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]
Production-Hardened Setup
FROM code.foss.global/host.today/ht-docker-node:alpine-node
# Non-root user
RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001
WORKDIR /app
COPY package*.json ./
RUN pnpm install --frozen-lockfile && pnpm cache clean
COPY --chown=nodejs:nodejs . .
RUN pnpm build
USER nodejs
EXPOSE 3000
CMD ["node", "dist/index.js"]
🔧 NVM Cheat Sheet
# Install a specific version
nvm install 22.5.0
# Use a version (current shell)
nvm use 22
# Set default (persists across shells / RUN steps)
nvm alias default 22
# Install and switch to latest LTS
nvm install --lts && nvm use --lts
# List installed versions
nvm ls
# Chain in a single Dockerfile RUN
RUN nvm install 22 && nvm use 22 && npm ci && npm test
🏗️ Building the Images
This project uses @git.zone/tsdocker for Docker image management.
# Install tsdocker
pnpm install -g @git.zone/tsdocker@latest
# Discover all Dockerfiles and their tags
tsdocker list
# Build all images (multi-arch: amd64 + arm64)
tsdocker build
# Run all test scripts
tsdocker test
# Push to a specific registry
tsdocker push code.foss.global
Manual Build (single image)
docker buildx build \
--platform linux/amd64,linux/arm64 \
-f Dockerfile_alpine-node \
-t your-registry/your-image:alpine-node \
--push .
Image Dependency Chain
Some images depend on others being in the registry first:
Dockerfile (:latest) ──► Dockerfile_lts (:lts)
──► Dockerfile_szci (:szci)
──► Dockerfile_fossglobal_preinstalled_* (:fossglobal_preinstalled_<ver>)
Dockerfile_alpine-node (:alpine-node)
──► Dockerfile_alpine-szci (:alpine-szci)
The standalone Alpine images (:alpine-bun, :alpine-deno) have no registry dependencies.
📊 Image Comparison
| Feature | Ubuntu :latest |
Alpine :alpine-node |
|---|---|---|
| Base Size | ~900 MB | ~200 MB |
| Build Tools | ✅ Full (gcc, g++, make, python3) | ⚠️ Install separately (apk add build-base) |
| Chromium | ✅ Pre-installed | ❌ |
| MongoDB | ✅ 8.0 | ❌ |
| Runtimes | Node + Bun + Deno + pnpm | Node + pnpm |
| Compatibility | ✅ Maximum (glibc) | ✅ Good (musl) |
| Multi-arch | ✅ amd64, arm64 | ✅ amd64, arm64 |
| tini init | ✅ | ✅ |
| Best for | Complex builds, E2E tests, full-stack dev | Production, CI/CD, microservices |
🐛 Troubleshooting
NVM command not found
Shouldn't happen in our images, but if it does:
export NVM_DIR="/usr/local/nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
Alpine native module build failures
Some npm packages require native build tools:
FROM code.foss.global/host.today/ht-docker-node:alpine-node
RUN apk add --no-cache python3 make g++
RUN pnpm install
Or use :alpine-szci which ships with build tools pre-installed.
Version not persisting across RUN steps
Each Dockerfile RUN creates a new shell. Use nvm alias default:
RUN nvm install 22 && nvm alias default 22
RUN node -v # ✅ v22.x.x
🔗 Links
- Source Code: code.foss.global/host.today/ht-docker-node
- NVM: github.com/nvm-sh/nvm
- tini: github.com/krallin/tini
- tsdocker: code.foss.global/git.zone/tsdocker
- Alpine Linux: alpinelinux.org
- Node.js Unofficial Builds: unofficial-builds.nodejs.org (musl support)
License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the LICENSE file.
Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
Company Information
Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
changelog.md for @host.today/ht-docker-node
2026-03-18 - 5.9.0 - feat(docker)
add a reusable Alpine base image and refactor Alpine variants to extend it
- introduces a new Dockerfile_alpine base image with NVM-managed Node.js for Alpine
- simplifies alpine-node, alpine-bun, and alpine-deno images by inheriting from the shared alpine base image
- adds jq to Debian and database images for improved shell tooling
- updates the release script to use verbose output and bumps @git.zone/tsdocker to ^2.1.0
2026-02-10 - 5.8.0 - feat(docker)
install Rust toolchain (rustup) and add aarch64 cross-compilation support to Docker images
- Install rustup and add /root/.cargo/bin to PATH in Dockerfile, Dockerfile_dbase, and Dockerfile_dbase_dind
- Add gcc-aarch64-linux-gnu package and run 'rustup target add aarch64-unknown-linux-gnu' in the main Dockerfile to enable cross-compilation
2026-02-07 - 5.7.0 - feat(docker)
install @ship.zone/szci in base images, add docker-entrypoint and use tini, remove deprecated Dockerfile_dbase_npmci, bump @git.zone/tsdocker devDependency to ^1.17.4
- Dockerfile_dbase: install @ship.zone/szci globally via pnpm
- Dockerfile_dbase_dind: add docker-entrypoint.sh and make it executable, consolidate chmod, set ENTRYPOINT to run tini with the new entrypoint and default CMD to ["bash"], and install @ship.zone/szci
- Remove Dockerfile_dbase_npmci (deleted)
- package.json: bump devDependency @git.zone/tsdocker from ^1.17.1 to ^1.17.4
2026-02-07 - 5.6.0 - feat(dockerfiles)
Add base Dockerfiles for dbase/dind, enable pnpm and stack-fix, update preinstalled image tooling and registries, and bump @git.zone/tsdocker devDependency
- Added Dockerfile_dbase: Alpine-based docker image with nodejs-current, pnpm installation, python/pip setup, compiles /lib/stack-fix.so and sets LD_PRELOAD, and enables pnpm unsafe-perm.
- Added Dockerfile_dbase_dind: multi-stage docker:dind build that installs same toolchain, compiles stack-fix.so in build stage, copies pnpm/python artifacts to final stage, and preserves LD_PRELOAD.
- Added Dockerfile_dbase_npmci: lightweight image FROM hosttoday/ht-docker-dbase:latest that installs @ship.zone/npmci globally via pnpm.
- Updated Dockerfile_fossglobal_preinstalled_##version##: switched from npm to pnpm and replaced several global packages (removed push.rocks/* and axios; added @git.zone/tsdocker, @git.zone/tsbundle, @git.zone/tools).
- Updated npmextra.json: cleared szci.dockerRegistries and simplified @git.zone/tsdocker registries/registryRepoMap to only use code.foss.global and preserved platforms/testDir.
- Bumped devDependency @git.zone/tsdocker from ^1.17.0 to ^1.17.1 (patch bump).
2026-02-07 - 5.5.2 - fix()
no changes detected — no release necessary
- No files changed in the provided git diff
- Current package.json version is 5.5.1
2026-02-07 - 5.5.1 - fix(docker)
normalize NODE_PATH and harden Dockerfile installs; use curl -fsSL; consolidate Alpine apk installs; update .dockerignore; bump @git.zone/tsdocker devDependency
- Change NODE_PATH to $NVM_DIR/versions/node/v... across Dockerfiles to match nvm layout
- Use curl -fsSL for non-interactive installs
- Run apt-get clean and remove /var/lib/apt/lists to reduce image size and ensure clean state
- Consolidate apk add commands and ensure python3 symlink and pnpm global installs in Alpine image
- Add .dockerignore entries to exclude build artifacts and include image_support_files
- Bump devDependency @git.zone/tsdocker from ^1.15.1 to ^1.16.0
2026-02-07 - 5.5.0 - feat(docker)
Rework Dockerfile into layered installs and add tooling (tini, chromium, MongoDB); simplify Alpine CI image Python/pip setup; add tsdocker devDependency; remove npmextra push flag; update README and registry links
- Dockerfile: split apt installs into logical layers, added tini, iputils-ping and dnsutils, moved chromium-browser into its own layer, and fixed apt cache cleanup (rm -rf)
- Dockerfile: add MongoDB 8.0 apt repository and install in a dedicated layer
- Alpine image (Dockerfile_alpine-szci): consolidated python3 and py3-pip install (removed ensurepip + manual pip upgrade)
- package.json: add devDependency @git.zone/tsdocker@^1.15.1
- npmextra.json: removed "push": false flag (affects CI/publish behavior)
- README: update registry URLs to code.foss.global, document tini and NVM behavior, refresh image descriptions and links
2026-02-06 - 5.4.0 - feat(ci)
replace npmci with szci across CI and images; add szci preinstalled images and make tini the PID 1 init in Docker images
- Replace @ship.zone/npmci with @ship.zone/szci in Gitea CI workflows (.gitea/workflows/docker_nottags.yaml, docker_tags.yaml) and update commands to use szci
- Add szci-specific Dockerfiles (Dockerfile_szci, Dockerfile_alpine-szci) and tests (test/test_szci.sh); remove npmci-specific files
- Install and use tini as PID 1 in multiple Dockerfiles and switch ENTRYPOINT to run tini for proper signal forwarding and zombie reaping
- Update metadata/manifest files (package.json, npmextra.json, readme.*, Dockerfile base tags) to reference szci and document the inclusion of tini
2026-02-06 - 5.3.0 - feat(docker)
add Chromium support for Puppeteer/Playwright and npm build/release scripts
- Add PUPPETEER_EXECUTABLE_PATH and CHROME_BIN env vars pointing to /usr/bin/chromium-browser for Puppeteer/Playwright compatibility
- Replace Google Chrome .deb download with apt-get install chromium-browser for multi-arch (amd64/arm64) compatibility
- Add npm scripts: 'build' -> 'tsdocker build' and 'release' -> 'tsdocker push' in package.json
2026-02-06 - 5.2.0 - feat(ci)
switch CI to use @git.zone/tsdocker and add tsdocker config and image tests
- Replace @ship.zone/npmci with @git.zone/tsdocker in CI workflow and use tsdocker commands: login, list, build, test, push
- Add npmextra.json configuration for @git.zone/tsdocker (registries, registryRepoMap, platforms, push/testDir)
- Add Dockerfile_alpine-npmci and per-image test scripts under test/ (alpine-bun, alpine-deno, alpine-node)
- Remove legacy Alpine Dockerfiles and legacy build/test scripts (Dockerfile_alpine_node/deno/bun/_npmci, build-alpine-images.sh, test-alpine-images.sh)
- Update LICENSE copyright owner to Task Venture Capital GmbH
2025-10-26 - 5.1.0 - feat(alpine-deno)
Improve alpine deno image: switch to alpine:edge and use native Deno package, remove glibc workaround, update NVM/PATH, add local tooling settings and expanded README
- Dockerfile_alpine_deno: switch base image from alpine:latest to alpine:edge to use Alpine community Deno package
- Install Deno via apk (native musl build) and remove previous glibc installation/workaround
- Remove DENO_INSTALL env and adjust PATH to include NVM-managed Node binary path
- Keep NVM installation and make nvm available globally; set NODE_VERSION_LTS and default alias
- Add .claude/settings.local.json with local permissions for build/run tooling
- Add / expand README (readme.md) with usage, flavours and NVM/npmci guidance
2025-10-26 - 5.0.148 - feat(alpine)
Major restructuring: Multi-architecture Alpine Docker images with modern runtime support
Breaking Changes:
- Removed
Dockerfile_alpine(replaced byDockerfile_alpine_node) - Removed
Dockerfile_iot(no longer needed with multi-arch approach) - Tag naming simplified:
:alpine-nodeinstead of:alpine-x64-nodeand:alpine-arm64-node
New Multi-Architecture Alpine Images (3 variants):
All images support both amd64 and arm64 architectures natively:
Dockerfile_alpine_node→:alpine-node- Alpine with Node.js LTS + NVM + pnpmDockerfile_alpine_deno→:alpine-deno- Alpine with Node.js LTS + NVM + DenoDockerfile_alpine_bun→:alpine-bun- Alpine with Node.js LTS + NVM + Bun
Technical Improvements:
- Multi-architecture support: Single Docker image works natively on both x64 (AMD64) and ARM64 (Apple Silicon, ARM servers)
- docker buildx integration: Build script uses buildx for proper multi-platform image creation
- Native performance: No emulation needed - images run at full native speed on both architectures
- Automatic platform selection: Docker automatically pulls the correct architecture variant
- Full NVM support in all Alpine images (v0.40.1)
- Node.js musl builds from unofficial-builds.nodejs.org for Alpine compatibility
- Significantly smaller image sizes (200-300MB vs 800MB+ Ubuntu)
- All images include NVM for flexible version management
- Reused wrapper scripts from Ubuntu base for consistency
- Added Bun and Deno runtime support
Build & Test Infrastructure:
- Updated
build-alpine-images.shto usedocker buildxwith native platform builds for local testing - Updated
test-alpine-images.shto test 3 multi-arch images instead of 9 architecture-specific images - Simplified test suite focuses on runtime functionality and NVM version switching
Documentation:
- Updated README with multi-architecture approach explanation
- Simplified examples using new tag names (
:alpine-node,:alpine-deno,:alpine-bun) - Added cross-platform development examples
- Documented native performance benefits
- Removed architecture-specific instructions (no longer needed)
2025-10-26 - 5.0.147 - feat(nvm)
Enable full nvm support in Docker builds and CI/CD workflows
- Added global nvm configuration in /etc/bash.bashrc (prepended before interactive check)
- Created bash-with-nvm wrapper for Dockerfile RUN commands
- Added intelligent ENTRYPOINT for runtime nvm support
- nvm commands now work directly in Dockerfile RUN without manual sourcing
- nvm commands work in CI/CD workflow bash -c scripts automatically
- Changed default SHELL directive to use nvm wrapper
- Backward compatible: npmci still available, ENV PATH preserved for fallback
- Non-bash shells fall back to ENV PATH (v20.12.2)
- Both interactive and non-interactive shells have full nvm access
2024-11-17 - 5.0.146 - fix(Dockerfiles)
Correct Docker image source host in various Dockerfiles
- Updated the source host from 'hosttoday/ht-docker-node' to 'host.today/ht-docker-node' in several Dockerfiles
2024-11-17 - 5.0.145 - fix(docs)
Minor documentation updates without code changes.
2024-11-17 - 5.0.144 - fix(ci)
Update Docker container source for workflow to new registry
- Changed Docker container image source in .gitea/workflows/docker_tags.yaml to code.foss.global.
2024-11-17 - 5.0.143 - fix(core)
No uncommitted changes
- No changes detected. All files are up-to-date.
2024-05-26 - 5.0.139 to 5.0.142 - Core updates
Routine updates to the core functionality.
2024-05-23 - 5.0.124 to 5.0.138 - Core updates
Routine updates to the core functionality.
2024-04-23 - 5.0.114 to 5.0.123 - Core updates
Routine updates to the core functionality.
2024-04-14 - 5.0.113 to 5.0.113 - Core updates
Routine updates to the core functionality.
2023-04-02 - 5.0.105 to 5.0.112 - Core updates
Routine updates to the core functionality.
2022-12-17 - 5.0.101 to 5.0.104 - Core updates
Routine updates to the core functionality.
2022-10-17 - 5.0.91 to 5.0.100 - Core updates
Routine updates to the core functionality.
2022-10-11 - 5.0.85 to 5.0.90 - Core updates
Routine updates to the core functionality.
2022-08-05 - 5.0.78 to 5.0.84 - Core updates
Routine updates to the core functionality.
2022-03-22 - 5.0.75 to 5.0.77 - Core updates
Routine updates to the core functionality.
2021-11-12 - 5.0.67 to 5.0.74 - Core updates
Routine updates to the core functionality.
2021-10-22 - 5.0.61 to 5.0.66 - Core updates
Routine updates to the core functionality.
2020-05-28 - 5.0.55 to 5.0.60 - Core updates
Routine updates to the core functionality.
2019-11-19 - 5.0.50 to 5.0.54 - Core and Snyk fixes
Core updates and restored Snyk to the latest version.
2016-08-31 - 4.3.2 to 4.3.5 - Core updates
Routine updates to the core functionality.
2016-06-01 - 4.3.1 - Multiple enhancements
Implemented various features and fixes in the project.
- Updated .gitlab-ci.yml multiple times
- Added Python3 support
- Added new features and fixed various issues