Image for charging bun, fnm, node, npm and zsh.
1.5K
Node, npm, bun, and fnm on top of
cartagodocker/zshβ
(Ubuntu 24.04 LTS + zsh + Oh My Zsh + Powerlevel10k).
Same layout as the zsh READMEβ . This page only expands what NodeBun adds. Shell, sudo, SSH, fonts, and the daily CLI are inherited β details live there.
| π¦ GitHub | https://github.com/CartagoGit/DockerNodeBunβ |
| π Docker Hub | https://hub.docker.com/r/cartagodocker/nodebunβ |
| π Changelog | CHANGELOG.mdβ |
| π·οΈ Versioning | VERSIONING.mdβ |
Tags are exact. There is no latest / stable. Pin the matrix you need.
FROM cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2
Pin
cartagodocker/zsh:v2.0.0. There is nolatest.
| Piece | Notes | |
|---|---|---|
| π§ | OS | Ubuntu 24.04 LTS β from cartagodocker/zshβ |
| π | zsh pin | cartagodocker/zsh:v2.0.0 |
| π | Interactive shell | zsh + Oh My Zsh + Powerlevel10k β CMD ["/usr/bin/zsh"], no ENTRYPOINT (zsh 2.0.0) |
| π» | Other shells | bash and sh (dash) β inherited |
| π’ | Node / npm / bun / fnm | Installed at build; on PATH for every uid and every shell |
| π | Listing / pager | Inherited from zsh β full list in Utilitiesβ |
| π§° | Daily CLI | Inherited from zsh (not reinstalled). Full inventory: Utilitiesβ |
| π | Catalogue | dockernodebun --help β zsh catalogue, then NodeBun extras (see Catalogue CLIβ ) |
| π | Network | Inherited: curl, wget, git, openssh-client (no sshd), ca-certificates |
| π | sudo | Inherited (NOPASSWD + sudo-password). Not overwritten when the base already has it |
| π | Locale | Inherited: LANG=C.UTF-8 Β· LC_ALL=C.UTF-8 |
| π§± | Build SHELL | ["/bin/sh", "-c"] β same as zsh |
No openssh-server, no ENTRYPOINT: docker run / Compose command: is the process (node --version works on zsh 2.0.0).
Not in this image (same as zsh): gcc/g++, python3, neovim, git-lfs, rclone, locales, man-db, nmap, no sshd, no Docker. NodeBun does not add a second CLI kit β only runtimes: fnm, one Node (matrix), npm, two bun binaries (AVX2 + baseline), libatomic1. Compilers / Docker client go in a further child. Drive this container with host docker.
sudo / dockerzsh / add_text_to_* come from cartagodocker/zsh:v2.0.0. Not reinstalled; no fallback for older zsh tags.
From zsh (not reinstalled): zsh README β Utilitiesβ (name β docs). Same aliases (lsβeza in interactive zsh/bash/sh). In-container: dockerzsh --help or dockernodebun --listing.
This image adds the tables below. Usage: Scripts for child imagesβ . zsh helpers: zsh README β Scriptsβ or dockernodebun --zsh-helpers.
On PATH (/usr/local/bin) for every uid and every shell. libatomic1 is for bun. /usr/local/bin/bun is a bash wrapper (AVX2 vs baseline from /proc/cpuinfo; chatter if BUN_WRAPPER_DEBUG=1). bunx is the same wrapper (bunx pkg β bun x pkg). fnm use is this shell only (FNM_DIR=/usr/share/fnm/store, 777).
| Command | Docs |
|---|---|
in-bash | Scriptsβ |
in-sh | Scriptsβ |
only-in-container | Scriptsβ |
skip-if-container | Scriptsβ |
dockernodebun | Catalogueβ |
docker images is uncompressed. Hub pull is gzip layers (smaller). On top of cartagodocker/zsh:v2.0.0.
Uncompressed (disk / docker images) | Compressed (Hub pull / download) | |
|---|---|---|
| zsh v2.0.0 (parent tree) | ~240β260β―MB | ~110β125β―MB |
Node official linux-x64 (26.3.1 / 22.21.1) | ~90β120β―MB unpacked | ~32β―MB / ~29β―MB .tar.xz |
| bun AVX2 zip + baseline zip | ~2 Γ 90β110β―MB unpacked | ~34β―MB + ~34β―MB zips |
| fnm | ~8β―MB | ~3β―MB zip |
libatomic1 | ~0.04β―MB | tiny |
| Whole tag (local 2.0.2 on Hub zsh 2.0.0, Node 26) | ~695β―MB | Hub layers (not listed for every matrix) |
Two bun builds on purpose: /usr/local/bin/bun is a bash wrapper (bun_wrapper.zsh β historical .zsh name, #!/bin/bash) that picks AVX2 vs baseline from /proc/cpuinfo. That doubles bun on disk. Silent unless BUN_WRAPPER_DEBUG=1. One Node is baked (fnm install of the matrix); extra fnm install at runtime grows FNM_DIR.
Disk β zsh 2.0.0 + Node + two bun + fnm: local smoke ~695β―MB uncompressed (Node 26). Hub NodeBun 2.0.0 on zsh 1.0.5 was ~642β―MB.
Defined in .github/matrices.ymlβ :
| Matrix | Node | Bun | npm | fnm | Status |
|---|---|---|---|---|---|
n22.21.1_b1.4.2 | 22.21.1 | 1.4.2 | 10.9.4 | 1.38.1 | β Node 22 LTS |
n26.3.1_b1.4.2 | 26.3.1 | 1.4.2 | 12.0.1 | 1.39.0 | β Node 26 current |
v{X.Y.Z}_n{node MAJOR.MINOR.PATCH}_b{bun MAJOR.MINOR.PATCH}
Examples: v2.0.2_n22.21.1_b1.4.2, v2.0.2_n26.3.1_b1.4.2.
X.Y.Z counts repo corrections (Dockerfile, wrapper, docs) and is published on all active matrices in parallel. Full policy: VERSIONING.mdβ .
Two different jobs. Mix them up and it looks like βeza is brokenβ.
Node / bun / npm / fnm are baked at docker build. docker run does not download them. On PATH (/usr/local/bin) for any uid and any shell.
| Tool | At build | At start |
|---|---|---|
| Node | fnm install β FNM_DIR=/usr/share/fnm/store | /usr/local/bin/node |
| npm | npm install -g npm@β¦ | /usr/local/bin/npm |
| bun / bunx | AVX2 + baseline zips; wrapper reads /proc/cpuinfo; bunx β bun x | /usr/local/bin/bun, /usr/local/bin/bunx |
| fnm | release zip | /usr/local/bin/fnm |
zsh extras (p10k) load from ~/.zshrc and need a TTY. Interactive bash/sh also get lsβeza. node / npm / bun do not need a TTY.
Needs a TTY (-it or exec -it).
# Hub: IMG=cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2
IMG=nodebun-local:dev
docker run --rm -it --user 1000:1000 -w /home/ubuntu \
-v "$HOME/.ssh:/$USER/.ssh:ro" \
-v "$HOME/.gitconfig:/$USER/.gitconfig:ro" \
"$IMG"
docker run --rm -it "$IMG" # root, no bind
lsβeza. bat works. p10k draws the prompt. node/npm/bun work in every shell. Inside zsh: bash, sh, exit. Interactive bash/sh alias lsβeza; no p10k.
The container stays up without a shell. Typical:
services:
app:
image: cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2
command: ["tail", "-f", "/dev/null"]
user: "1000:1000"
working_dir: /work
volumes:
- .:/work
That process is tail, not zsh, and not a TTY. No prompt, no eza aliases, no p10k. Attach when you want the shell:
docker compose exec app zsh # prompt + eza + bat + p10k
docker compose exec app bash # bash; node/npm/bun still on PATH
docker compose exec app bun install
docker run --rm cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2 node --version
docker run --rm image bash and docker run --rm image node --version work because there is no ENTRYPOINT swallowing the command (cartagodocker/zsh:v2.0.0).
Inherited from zsh. Global files (/usr/share/globally/.zshrc) are 644 root:root β uid 1000 cannot overwrite them. Use sudo or add_text_to_zshrc (NOPASSWD). node/npm/bun do not need sudo.
docker run --rm -it --user 1000:1000 cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2
# inside:
sudo -n id # default: no password
sudo-password # prompt; afterwards sudo asks for it
sudo-password 'secret' # from arg (visible in ps)
sudo-nopasswd # back to NOPASSWD
Password at start (not baked into the image):
docker run --rm -it -e SUDO_PASSWORD=secret cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2
Compose user: "1000:1000" drops extra groups, so the sudoers rule is ALL, not %sudo.
Same contract as cartagodocker/zshβ . The container only emits Unicode. The host terminal draws glyphs.
| What | Needs on the host | |
|---|---|---|
| π· | Powerlevel10k separators, git icons, eza file icons | A Nerd Fontβ (CaskaydiaCove / Cascadia Code NF) |
| π³ | Prompt whale (os_icon) | An emoji font β Segoe UI Emoji (Windows), Apple Color Emoji (macOS), Noto Color Emoji (many Linux desktops). Some Linux terminals have none β tofu. Same Unicode everywhere; the font is local. |
VS Code:
"terminal.integrated.fontFamily": "'Cascadia Code NF', 'CaskaydiaCove Nerd Font', Consolas, monospace"
Without a Nerd Font you get boxes on powerline / ls icons β not an image bug.
add_text_to_zshrc, add_text_to_p10k, share_config_globally, sudo-password, sudo-nopasswd β same CLI as zshβ . Write /usr/share/globally/...; sudo if needed. Full text: dockerzsh --helpers or dockernodebun --zsh-helpers.
Most people never type these (bash pepe.sh is enough). Same Makefile on host and in-container. Detect /.dockerenv or IS_INTO_CONTAINER=true.
in-bashbash --login so /etc/profile.d/nodebun.sh loads (BUN_* / FNM_*). For snippets that are not zsh-safe (set -o pipefail, [[ ]], bash arrays). No args: interactive bash.
in-bash
in-bash -c 'set -o pipefail; npm test | tee log'
in-bash script.sh
in-shPOSIX sh -l (dash + login env). Same idea as in-bash for portable snippets.
in-sh
in-sh -c 'case $1 in *.sh) echo posix ;; esac'
in-sh script.sh
only-in-containerRun CMD only inside this container. No args: exit 0 inside, 1 outside (predicate). Outside with a command: error, exit 1.
only-in-container # 0 inside, 1 on the host
only-in-container bun run test # skip on the host
skip-if-containerNo-op inside (exit 0); run CMD on the host. For host-only tools (adb, docker, osascript). No args on the host: error.
skip-if-container adb start-server
Catalogue dump of these four: dockernodebun --helpers.
Inherited from zsh. Bind host ~/.ssh and type ssh / git. Root or any uid β one volume. Git author is not the SSH key: bind ~/.gitconfig (or GIT_AUTHOR_NAME + GIT_AUTHOR_EMAIL). Full contract: zsh README β SSHβ .
services:
app:
image: cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2
volumes:
- ~/.ssh:/${USER}/.ssh:ro
- ~/.gitconfig:/${USER}/.gitconfig:ro
docker run --rm -it \
-v "$HOME/.ssh:/$USER/.ssh:ro" \
-v "$HOME/.gitconfig:/$USER/.gitconfig:ro" \
cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2
# inside: ssh [email protected]
# git commit # author = host user.name, not ubuntu@id
${USER} is the host name. Docker needs an absolute target (/${USER}/.ssh), not ${USER}/.ssh. Not SSH-into-the-container β attach with docker exec -it β¦ zsh.
| Variable | Meaning |
|---|---|
NODE_DEFAULT_VERSION | Matrix Node |
FNM_HOME / FNM_DIR / FNM_BIN | /usr/share/fnm, store, bin |
BUN_HOME / BUN_INSTALL | /usr/share/bun |
IS_INTO_CONTAINER | true |
VERSION | Convenience X.Y.Z. A child FROM nodebun that sets its own VERSION overwrites this. |
NODEBUN_IMAGE_VERSION | This NodeBun tag. dockernodebun --version uses it, not VERSION. |
ZSH_IMAGE_VERSION | Parent zsh tag (cartagodocker/zsh). dockerzsh --version uses it. |
LANG / LC_ALL | Inherited C.UTF-8 |
Login shells (su -, bash -l) drop Docker ENV. /etc/profile.d/nodebun.sh re-exports NodeBun vars (also from /etc/zsh/zprofile β Ubuntu login zsh does not source /etc/profile). Same script on every matrix. This imageβs Node / X.Y.Z live in /usr/share/nodebun/build.env (from ARG at build) and fill only when ENV is unset. Interactive zsh still runs fnm env from .zshrc.
FNM_DIR is 777 (same as bun): any uid can fnm install / fnm use. Homes and /etc/skel get ~/.local/share/fnm β that store, plus ~/.local/state (fnm multishells) owned by that user so fnm env works as uid 1000.
fnm install 20.19.0
fnm use 20.19.0 # this shell only; a new shell is back on the matrix
dockernodebun)Inside a running container dockernodebun is the zsh catalogue first (dockerzsh --help), then NodeBun extras. Not the host docker CLI.
docker run --rm cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2 dockernodebun --help
docker compose exec app dockernodebun --help
The full dump is long on purpose. Filter by section. NodeBun ids stay here; zsh ids go to dockerzsh.
dockernodebun --sections | -s # zsh ids + NodeBun ids
dockernodebun --runtimes # node / npm / bun / fnm
dockernodebun --helpers # in-bash, in-sh, only-in-container, skip-if-container
dockernodebun --zsh-helpers # add_text_to_zshrc, add_text_to_p10k, share_config_globally, sudo-password, sudo-nopasswd, git-from-host (zsh)
dockernodebun --env # NODE_DEFAULT_VERSION, FNM_DIR, BUN_*, IS_INTO_CONTAINER
dockernodebun --shells # zsh section (forwards)
dockernodebun shells env # mix zsh + NodeBun sections
dockernodebun --version | -v # image identity (NODEBUN_IMAGE_VERSION)
dockernodebun --list | -l # tool names (this image + zsh)
dockernodebun --list --version | -l -v
dockernodebun runtimes --version | runtimes -v
dockernodebun node --version | node -v
| Id | Where | Section |
|---|---|---|
nodebun | this image | Intro (PATH at build, no ENTRYPOINT, TTY vs keep-alive) |
runtimes | this image | node, npm, npx, bun, fnm |
helpers | this image | in-bash, in-sh, only-in-container, skip-if-container |
env | this image | NODE_DEFAULT_VERSION, FNM_*, BUN_*, IS_INTO_CONTAINER |
shells, listing, edit, archives, network, system, extras, helpers, fonts | zsh base | Same ids as dockerzsh --sectionsβ β full tool list in zsh README β Utilitiesβ |
zsh-helpers | zsh base | add_text_to_zshrc, add_text_to_p10k, share_config_globally, sudo-password, sudo-nopasswd, git-from-host, dockerzsh |
--helpers on this CLI is NodeBun. zsh helpers: dockernodebun --zsh-helpers or dockerzsh --helpers. Unknown ids exit 2.
FROM cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2
WORKDIR /app
COPY package.json bun.lock ./
RUN bun install
Keep SHELL ["/bin/sh", "-c"] if you override it (cartagodocker/zsh:v2.0.0 already sets it).
docker build \
--build-arg VERSION=2.0.2 \
--build-arg NODE_DEFAULT_VERSION=26.3.1 \
--build-arg BUN_VERSION=1.4.2 \
--build-arg FNM_VERSION=1.39.0 \
--build-arg NPM_VERSION=12.0.1 \
-t cartagodocker/nodebun:v2.0.2_n26.3.1_b1.4.2 \
-f ./Dockerfile ./
The GitHub workflow fills those from .github/matrices.yml.
Note: when bumping
ARG VERSIONin theDockerfile, also update theENV VERSION=β¦andENV NODEBUN_IMAGE_VERSION=β¦literals that follow the multiline ENV block. The workflow only injects the ARG, not the literal ENVs β they exist becausecartagodocker/zsh:v2.0.0already exportsENV VERSION=2.0.0and Docker would otherwise shadow the ARG with that inherited value. See[2.0.2]in CHANGELOG.mdβ .
GitHub Actions (secrets DOCKERHUB_USERNAME, DOCKERHUB_PASSWORD; variable DOCKERHUB_REPO):
| Trigger | What happens |
|---|---|
Git tag v{X.Y.Z} | One Hub tag per active matrix if new (skip existing) + GitHub Release for v{X.Y.Z} (replaced if it exists) β docker-hub-update.ymlβ |
Git tag v{X.Y.Z}_nβ¦_bβ¦ | That matrix only. Skip Hub if the tag exists. GitHub Release for that matrix tag (replaced if it exists; not latest). No Hub :latest. |
Push to main that changes README.md | Hub long description (full_description β€ ~25β―000 chars) β update-dockerhub-description.ymlβ |
git tag v2.0.1
git push origin main v2.0.1
See CHANGELOG.mdβ and VERSIONING.mdβ .
Content type
Image
Digest
sha256:a536445c3β¦
Size
232.4 MB
Last updated
about 5 hours ago
docker pull cartagodocker/nodebun:v2.0.2_n22.21.1_b1.4.2