Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

Β 

History

87 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🟒 cartagodocker/nodebun

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 no latest.


πŸ“¦ What's in the image

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.


🧰 Utilities

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.

Runtimes (NodeBun)

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).

Tool Docs
node Node.js
npm / npx npm Β· npx
bun / bunx bun Β· bunx
fnm fnm

NodeBun helpers (ours)

Command Docs
in-bash Scripts
in-sh Scripts
only-in-container Scripts
skip-if-container Scripts
dockernodebun Catalogue

πŸ“ Image size

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.


🏷️ Runtime matrices

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.


▢️ How to run it

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.

πŸ–₯️ Interactive prompt (eza, bat, p10k)

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.

🧊 Keep-alive (Compose)

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).


πŸ” sudo

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.


🎨 Fonts and icons

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.


🧩 Scripts for child images

From zsh (inherited)

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.

NodeBun only

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-bash

bash --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-sh

POSIX 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-container

Run 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-container

No-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.


πŸ”‘ SSH (client only β€” no sshd)

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 git@github.com
#         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.


🌍 Environment

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

πŸ“– Catalogue CLI (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.


🧱 Child image

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).


πŸš€ Build and publish

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 VERSION in the Dockerfile, also update the ENV VERSION=… and ENV NODEBUN_IMAGE_VERSION=… literals that follow the multiline ENV block. The workflow only injects the ARG, not the literal ENVs β€” they exist because cartagodocker/zsh:v2.0.0 already exports ENV VERSION=2.0.0 and 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.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages