nodejs/docker-node: the official Node.js image and its tag variants
Official Docker Image for Node.js :whale: :turtle: :rocket:
At a glance
- What is it?
- The official Node.js Docker image gives you a prebuilt Node runtime and npm (plus Yarn v1 Classic for Node.js 25 and below), with Debian, slim and Alpine variants. The choice between them is mostly about libc and image size, not features.
- Who is it for?
- Adopt these images if you want a maintained, versioned Node runtime without building one yourself, and if your dependency tree is built for glibc, use node:<version> or node:slim. Do not adopt node:alpine for a project with native modules unless you have confirmed musl builds exist for every one of them, and do not pin a major version you have not checked against the Node.js release schedule.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Dockerfile, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- nodejs/docker-node8,596 ★ · +3
| Repository | 2026-09-22 | 2026-11-13 |
|---|---|---|
| nodejs/docker-node | 8.6k | 8.6k |
3 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
What the official Node.js image actually replaces
Anyone deploying a Node.js service needs a runtime inside a container, and the usual way to get one is to write a Dockerfile that installs Node on top of a base image. That means choosing a base, adding a NodeSource or tarball step, pinning a version, and repeating the exercise whenever the base moves. The nodejs/docker-node repository maintains that work as a published set of images instead. The README describes it as "the official Node.js docker image, made with love by the node community", and the package.json describes the repository's job plainly: "Build official Docker images for Node.js".
The audience is anyone who runs Node in a container: application teams writing a service Dockerfile, CI pipelines that need a Node toolchain, and platform teams that build internal base images on top of a known runtime. It is less useful to someone running Node directly on a host, or to someone who wants a Node distribution with a package manager other than npm and Yarn v1 Classic baked in. The images are not a framework, a build system or a deployment tool. They are the runtime layer, and nothing more.
The repository is not archived, and the last push was on 2026-10-28, so the tag set is being updated. That matters because a Node image is only as good as its release cadence: a stale image means a stale runtime.
How the tag variants differ, and why Alpine is the real fork in the road
The README splits the images into variants. node:<version> is the default and is based on buildpack-deps, which the README says "by design, has a large number of extremely common Debian packages", reducing what derived images must install. node:lts selects the Active Long Term Support version of Node.js rather than a specific major. node:bookworm and node:trixie are named for their Debian release, and node:slim is the trimmed Debian build.
node:alpine is the interesting one. It is based on Alpine Linux, and because the base alpine image is smaller than the corresponding debian image, the README states that node:alpine images are around 25% smaller than the Debian-based node:slim images. The cost is the C library. Alpine uses musl libc, not the GNU C library glibc that Debian uses, and the README says that applications written for Debian (glibc) generally will not work on Alpine. That single sentence is the most consequential line in the document. If your dependency tree contains anything compiled against glibc, the Alpine tag is not a drop-in replacement for the Debian one, and a smaller image is not worth a runtime that cannot load your native modules.
Architecture support is not uniform across variants. The README points to versions.json, which "lists all supported variants for all of the architectures that we support now". That file, not the tag list on Docker Hub, is the source of truth for whether a given variant exists for a given platform. The README also has a section on musl builds for Alpine.
One packaging detail is easy to miss: Yarn v1 Classic is included in node images with Node.js 25 and below. The README calls it "the legacy package manager" and links to the Yarn v1 Classic bundling section. If your build calls yarn, the tag you pick determines whether that binary is present.
Installing and running your first Node.js container
There is nothing to install from this repository. The images are pulled from Docker Hub, and the README links to https://hub.docker.com/_/node/ as the place to view the currently supported floating and pinned tags. The README's first example is a two-line Dockerfile that selects a Node major and declares the port the application listens on:
# specify the node base image with your desired version node:<version>
FROM node:24
# replace this with your application's default port
EXPOSE 8888After that, the README gives the build and run pair. The build tags the image as my-nodejs-app, and the run starts it interactively with --rm so the container is removed on exit:
$ docker build -t my-nodejs-app .
$ docker run -it --rm --name my-running-app my-nodejs-appFor a project that already has a package.json with a start script, the README offers a Compose file. Note the working directory and the named user, which keep the process off root:
services:
node:
image: 'node:24'
user: 'node'
working_dir: /home/node/app
environment:
- NODE_ENV=production
volumes:
- ./:/home/node/app
ports: # use if it is necessary to expose the container to the host machine
- '8888:8888'
command: ['npm', 'start']Run it with docker-compose up -d. The README notes that this Compose example mounts your current directory, including node_modules, into the container. For a single script, no Dockerfile is needed at all:
$ docker run -it --rm --name my-running-script -v "$PWD":/usr/src/app -w /usr/src/app node:24 node your-daemon-or-script.jsThat command mounts the working directory at /usr/src/app, sets it as the working directory, and runs your file with the image's node binary. If npm output is too quiet or too loud, the README documents NPM_CONFIG_LOGLEVEL as an environment variable settable with ENV in a Dockerfile or -e on docker run, and npm --loglevel=info as the command-line equivalent. The default npm loglevel is notice, which already includes warn and error.
Where these images stop being the right tool
The Alpine libc split is the clearest failure mode, but it is not the only one. The default node:<version> tag is built on buildpack-deps, which the README itself describes as carrying a large number of common Debian packages. That is convenient for derived images and wasteful for a final production layer. If image size matters, the README's own comparison points you at node:slim or node:alpine, and the choice between those two is decided by libc, not by size.
A second boundary is version selection. node:lts follows the Active LTS line, so the Node major under that tag changes over time. A build that pins node:lts is not reproducible across that change. Pinning node:24 or node:22 fixes the major but leaves you responsible for tracking Node.js security releases yourself. The README has a Long Term Support section and a Release Availability section that cover this.
A third is that this is a runtime image, not an application image. It does not install your dependencies, run a build step, or manage a process supervisor. The Compose example runs npm start directly as the container command, which means npm runs as PID 1 and signal handling is whatever npm and your start script do with it. The repository ships a docker-entrypoint.sh at the top level, so check what it does rather than assume it forwards signals or reaps zombies. If you need that, verify it in the file before relying on it.
Finally, the README is a usage document, not an operations manual. The repository does contain a keys/ directory and an update-keys.sh script, which suggests key material is part of the build process.
How this compares to building Node in your own base image
The realistic alternative is a self-built image: start from debian:bookworm-slim or alpine, download the Node tarball or add a package repository, and install Node yourself. The difference is who owns the version matrix. With nodejs/docker-node you inherit a set of tags that the maintainers keep aligned with Node.js releases and with the Debian and Alpine bases, and you get npm preinstalled, plus Yarn v1 Classic on Node.js 25 and below. With a self-built image you control exactly which packages land in the layer, which is the only way to get a genuinely minimal image, and you avoid a dependency on a third party's rebuild cadence.
The trade is maintenance. A self-built image needs a process for picking up Node security releases and base-image updates, and that process is the thing this repository exists to provide. The other difference is reproducibility of the base. The README notes that node:<version> derives from buildpack-deps, so the package set underneath your application is larger than what a hand-rolled slim base would contain. If your threat model or your registry quota cares about layer count and installed packages, the official default tag is the heavier option, and node:slim or a self-built base is the lighter one.
Within the official images, the README's own framing makes the internal comparison easy: node:slim for a smaller Debian image, node:alpine for roughly 25% less than that, at the cost of musl libc. There is no variant that is both glibc-compatible and Alpine-sized.
Maintenance, licensing and what the repository tells you about upgrades
The repository is MIT licensed, and the LICENSE file sits at the top level. That covers the build scripts and templates in this repository. It does not automatically describe the licences of the contents of the published images, which include Node.js itself, npm, Yarn v1 Classic and the Debian or Alpine userland. If you redistribute an image, the licence obligations of those components are a separate question for your own legal review.
The upgrade cost is mostly about tag choice. The README's guidance is that node:<version> is "the defacto image" and that if you are unsure what you need, you probably want that one. In practice the maintenance burden lands in two places: tracking the Node.js release schedule so a pinned major does not go unsupported, and re-testing native dependencies whenever you move between the Debian and Alpine families. Moving from node:24 to node:26 is a Node.js major upgrade with its own breaking changes; moving from node:24 to node:24-alpine is a libc change that can break a build without any Node.js change at all.
The repository's own tooling is worth knowing about if you fork or mirror it. package.json exposes a lint script that runs doctoc, prettier and eslint checks, plus a check:markdown-links script that runs markdown-link-check over the README and docs. That is a signal about how the README is maintained, not a feature of the images. The repository has no published GitHub releases, so treat the published image tags on Docker Hub, not GitHub releases, as the versioning surface.
Editorial conclusion
Adopt these images if you want a maintained, versioned Node runtime without building one yourself, and if your dependency tree is built for glibc, use node:<version> or node:slim. Do not adopt node:alpine for a project with native modules unless you have confirmed musl builds exist for every one of them, and do not pin a major version you have not checked against the Node.js release schedule. Before your first build, read versions.json to confirm the variant exists for your architecture, and check docs/BestPractices.md, the Best Practices Guide the maintainers publish.
Frequently asked questions
How do I run Node.js on Docker?
Use the official image directly for a single script, or write a Dockerfile with FROM node:24 and build it. The README shows docker run -it --rm --name my-running-script -v "$PWD":/usr/src/app -w /usr/src/app node:24 node your-daemon-or-script.js for the no-Dockerfile case.
How do I use the docker node image with npm?
The images include npm, and the README's Compose example sets working_dir to /home/node/app and command to ['npm', 'start'], which runs the start script from your package.json. It warns that the example mounts your current directory including node_modules into the container.
What is the difference between docker node slim and alpine?
node:slim is a trimmed Debian image and node:alpine is based on Alpine Linux, which the README says makes it around 25% smaller than node:slim. Alpine uses musl libc instead of glibc, and the README states that applications written for Debian generally will not work on Alpine.
What is docker node 20?
It would be the node:20 tag for the Node.js 20 major line, but the repository's top level now has only 22/, 24/ and 26/ version directories, so check Docker Hub before relying on it. The README's variant documentation covers node:<version> generally and points to Docker Hub for the list of currently supported floating and pinned tags.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nodejs-docker-node)Star history chart for your README
[](https://hysenlabs.com/projects/nodejs-docker-node)Was this useful?