Run Node.js in Docker containers — no need to install Node.js or nvm on your host machine.
No need to install Node.js or nvm on your host. Freely use and switch Node versions with just Docker Desktop.
Docker Node Version Mux (Multiplexer) for Windows is a Windows batch script tool that runs Node.js through Docker containers.
No need to install Node.js, no need to learn version management tools. Just Docker Desktop, and you can use any Node.js version in any directory.
The core principle is simple: each command (node, npm, npx) is wrapped in a .cmd batch script that internally calls docker run to start the corresponding node:*-alpine image, mounting the current working directory to /app inside the container.
You can even use the following command directly instead of node, npm, npx:
docker run --rm -it --init --network host -v "$(pwd):/app" -v npm-config-data:/root -w /app node:22-alpine npm install axios- No Node.js installation required — No Node.js runtime needed on the host
- Free version switching — Append
+versionto any command to temporarily switch Node versions (e.g.,+20,+18,+22) - Default version config — Set a default version during installation for daily use
- Command prefix support — Configure a command prefix (e.g.,
d) to generatednpm,dnode,dnpx, avoiding conflicts with system commands - Generic shell execution —
nodeshruns any shell command inside a container (ls,tar,curl, etc.) - Port mapping — Supports
--network hostor custom port mapping ranges for running web services - Persistent npm cache — Uses Docker volume
npm-config-datato persist npm configuration across runs - Ready to use — Install script automatically configures PATH, ready to use from any terminal
- OS: Windows 10/11 (or Windows Server 2016+)
- Docker: Docker Desktop for Windows (must be installed and running)
- PowerShell: For running install/uninstall scripts
# Clone or download this project, then run in the project directory:
powershell -ExecutionPolicy Bypass -File .\install.ps1The install script will guide you through the following configuration:
- Command prefix — Enter a prefix to avoid conflicts with system commands (e.g., enter
dto generatednpm,dnode,dnpx; leave empty fornpm,node,npx) - Default Node version — Default
22, can specify other versions like20,18 - Port mapping — Enter
0for--network host, or a port/range like12480-12499for-p 12480-12499:12480-12499 - Add to PATH — Choose whether to add the
bin\directory to your user PATH
After installation, open a new terminal window and use the following commands:
(with prefix d as an example)
# Check Node version
dnode --version
# Install dependencies
dnpm install
# Run npx commands
dnpx create-vite@latest
# Use a specific Node version (temporary switch)
dnpm +20 install
dnode +18 --version
dnpx +22 create-react-app my-app
# Run arbitrary shell commands in a container
nodesh ls -la
nodesh tar -czvf demo.tar.gz demo/
nodesh +20 node -e "console.log('Hello from Node 20')"nodesh helppowershell -ExecutionPolicy Bypass -File .\uninstall.ps1The uninstall script will:
- Delete the
bin\directory (all generated command files) - Delete the
var\directory (configuration files) - Remove
bin\from the user PATH
Note: Docker images and volumes are not automatically removed. To clean up manually:
docker volume rm npm-config-data docker system prune -a
powershell -ExecutionPolicy Bypass -File .\test.ps1The test script verifies that all commands work correctly, including version switching and file operations.
| Command | Description |
|---|---|
{prefix}node |
Run Node.js in Docker |
{prefix}npm |
Run npm in Docker |
{prefix}npx |
Run npx in Docker |
nodesh |
Run any shell command in Docker |
{prefix}is the command prefix configured during installation, empty by default.
All commands support temporary Node version switching via the +version parameter:
# Use Node 20
dnode +20 -e "console.log(process.version)"
# Install dependencies with Node 18
dnpm +18 install
# Run npx with Node 22
dnpx +22 create-vue@latestThe version must correspond to a node:* image tag on Docker Hub (e.g., 20, 18, 22, 23, etc.).
The port mapping configured during installation determines how the container exposes ports:
0— Uses--network hostmode (requires Host networking enabled in Docker Desktop settings)- Other values — Uses
-p PORT:PORTmapping, e.g.,12480-12499maps ports 12480 through 12499
nodejs-docker/
├── install.ps1 # Install script
├── uninstall.ps1 # Uninstall script
├── test.ps1 # Test script
├── README.md # This file (English)
├── README-zh.md # Chinese documentation
├── bin/ # Generated command files (created during install)
│ ├── {prefix}node.cmd
│ ├── {prefix}npm.cmd
│ ├── {prefix}npx.cmd
│ └── nodesh.cmd
├── lib/ # Command templates
│ ├── node.cmd-simple
│ ├── npm.cmd-simple
│ ├── npx.cmd-simple
│ └── nodesh.cmd-simple
└── var/ # Configuration files (created during install)
├── CMD_PREFIX
├── DEFAULT_NODE_VERSION
└── EXPOSE_PORT
Each .cmd script is essentially a wrapper around docker run:
docker run --rm -it --init [network args] \
-v "%CD%:/app" \ # Mount current directory to container
-v npm-config-data:/root \ # Persist npm cache
-w /app \ # Set working directory to /app
"node:{version}-alpine" \ # Use specified Node image
{command} {args} # Execute command--rm— Automatically remove container on exit-it— Interactive terminal--init— Use init process for signal handlingnpm-config-datavolume — Persists npm configuration and global cache across runs
The install script detects existing Node.js installations. If a conflict is detected, we recommend:
- Uninstall the system Node.js, or
- Set a command prefix during installation (e.g.,
d), and usednode,dnpmto avoid conflicts
Re-run install.ps1.
Or directly edit the var\DEFAULT_NODE_VERSION file.
Re-run install.ps1.
Or edit the var\CMD_PREFIX file, then manually rename the corresponding command files in the bin\ directory (e.g., rename npm.cmd to dnpm.cmd).
Re-run install.ps1.
Or directly edit the var\EXPOSE_PORT file.
--network host mode requires the corresponding feature to be enabled in Docker Desktop first. Enable it as follows:
- Open Docker Desktop
- Click the ⚙️ Settings icon in the top right
- Go to Resources → Network
- Check Enable host networking (requires Docker Desktop 4.29+)
- Click Apply & Restart
If you can't find this option, make sure your Docker Desktop version is 4.29 or higher.
No. node, npm, npx, and nodesh are all .cmd batch files — they are not affected by PowerShell's ExecutionPolicy and work in both PowerShell and cmd.
PowerShell execution policy only affects .ps1 scripts (like install.ps1, uninstall.ps1, test.ps1), which is why those need -ExecutionPolicy Bypass to run.
For daily use of dnode, dnpm, nodesh, etc., just type them in your terminal — no extra setup needed.
Yes. npm configuration is stored in the Docker volume npm-config-data, so it persists even when containers are removed.
Some might want to mount /usr/local/lib/node_modules separately. This is not recommended for the following reasons:
- Version conflicts — Global packages from different Node versions may be incompatible.
- Permission issues — The ownership and permissions of
/usr/local/lib/node_modulesin Alpine images may not match the mounted volume, causingnpm install -gto fail. - Cross-version pollution — Switching versions may cause global commands to point to incompatible native modules.
- Against design philosophy — Simplicity, lightness, and local dependencies are the project's design philosophy. Installing components globally goes against the container mindset.
That said, you can design separate volume names for different Node versions to solve compatibility issues. If you really need custom mount behavior, edit the .cmd-simple template files in the lib\ directory, modify the volume mount section, then re-run install.ps1.
MIT