docker-node Documentation

Official Docker Image for Node.js :whale: :turtle: :rocket:

8,577 stars Dockerfile Dockerfile 1 file ยท ~6,213 tokens #docker#docker-image#docker-node#dockerfile#node#nodejs
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy docker-node on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name docker-node --restart always nodejs/docker-node:latest

1. Project Overview & Quickstart (nodejs/docker-node)

File: README.md

Node.js

node - Docker Official Images on Docker Hub


The official Node.js docker image, made with love by the node community.

Table of Contents

What is Node.js?

Node.js is a platform built on Chrome's JavaScript runtime for easily building
fast, scalable network applications. Node.js uses an event-driven, non-blocking
I/O model that makes it lightweight and efficient, perfect for data-intensive
real-time applications that run across distributed devices.

See: https://nodejs.org

How to use this image

Create a `Dockerfile` in your Node.js app project

dockerfile
# specify the node base image with your desired version node:<version>
FROM node:24
# replace this with your application's default port
EXPOSE 8888

You can then build and run the Docker image:

console
$ docker build -t my-nodejs-app .
$ docker run -it --rm --name my-running-app my-nodejs-app

If you prefer Docker Compose:

yml
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']

You can then run using Docker Compose:

console
$ docker-compose up -d

Docker Compose example mounts your current directory (including node_modules) to the container.
It assumes that your application has a file named package.json
defining start script.

Best Practices

We have assembled a Best Practices Guide for those using these images on a daily basis.

Run a single Node.js script

For many simple, single file projects, you may find it inconvenient to write a
complete Dockerfile. In such cases, you can run a Node.js script by using the
Node.js Docker image directly:

console
$ 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

npm loglevel

The default npm loglevel
is notice, which includes also the levels warn and error.
If you need to set a different loglevel for npm, follow these example instructions:

Dockerfile

If you create your own Dockerfile which inherits from the node image, you can
use ENV to set the NPM_CONFIG_LOGLEVEL environment variable.

dockerfile
FROM node:lts
ENV NPM_CONFIG_LOGLEVEL=info
...

Docker Run

If you run the node image using docker run, you can use the -e flag to
set the NPM_CONFIG_LOGLEVEL environment variable.

console
$ docker run -e NPM_CONFIG_LOGLEVEL=info node:lts ...

npm run

If you are running npm commands, you can use the --loglevel command line flag
to control the verbosity of the output.

console
$ docker run node:lts npm --loglevel=info ...

Image Variants

The node images come in many flavors, each designed for a specific use case.
All of the images contain pre-installed versions of node which includes also
npm. For each
supported architecture, the supported variants are different. In the file:
versions.json, it lists all supported variants for all of
the architectures that we support now.

The legacy package manager
Yarn v1 Classic
is included in node images with Node.js 25 and below. See
Yarn v1 Classic bundling for details.

View the list of currently supported floating and pinned tags on Docker Hub.

`node:`

This is the defacto image. If you are unsure about what your needs are, you
probably want to use this one. It is designed to be used both as a throw away
container (mount your source code and start the container to start your app), as
well as the base to build other images off of. This tag is based off of
buildpack-deps.
buildpack-deps is designed for the average user of docker who has many images
on their system. It, by design, has a large number of extremely common Debian
packages. This reduces the number of packages that images that derive from it
need to install, thus reducing the overall size of all images on your system.

`node:lts`

This is a special form of node:<version> that selects the
Active Long Term Support version of Node.js. See also Long Term Support below for more detail.

`node:alpine`

This image is based on
Alpine Linux. Because base
alpine images are smaller
than corresponding base
debian images, the resulting
node:alpine Docker images are around 25% smaller than the
Debian-based node:slim images.

Alpine images use the C library
musl libc, not the GNU C library
glibc used by Debian.

Generally, applications written for Debian (glibc) will not run under Alpine (musl).
Some compatibility issues may be resolvable by installing the Alpine
gcompat
GNU C Library compatibility layer for musl package.
Use apk add --no-cache gcompat to install.

Tools such as git or bash are not included in node:alpine* based images. The
Alpine documentation describes how to find and
install additional packages using apk (Alpine Package Keeper).

The
Best Practices document, in the section
Smaller images without npm/yarn,
shows how to produce a custom image by removing package managers in a multi-stage build.

`node:bullseye`

This image is based on version 11 of
Debian, available in
the debian official image.

`node:bookworm`

This image is based on version 12 of
Debian, available in
the debian official image.

`node:trixie`

This image is based on version 13 of
Debian, available in
the debian official image.

`node:slim`

This image does not contain the common packages contained in the default tag and
only contains the minimal packages needed to run node. Unless you are working
in an environment where only the Node.js image will be deployed and you have
space constraints, we highly recommend using the default image of this
repository.

Long Term Support (LTS)

Production applications should only use LTS releases.

Refer to Node.js Releases for a description
of release phases and schedule.

If no version selection is made in a tag, for example, node:slim,
then the Current release is selected.
node images using the Active LTS release are published with an lts floating tag
to aid their selection. node:lts can be used on its own, or in combination with other tags
such as node:lts-slim. To select a node image based on a Maintenance LTS version
use the literal node version in the tag.

Release Availability

This repo automatically triggers a process to build new node images when Node.js releases
become available. The build processes can take several hours to complete.

Images may initially appear on Docker Hub
with incomplete or missing OS/ARCH listings as the build process first publishes a tag
and then backfills each architecture when ready.
During this time, if you try to pull the image, you may see an error
message "no matching manifest". In this case, check back later.
(See Docker Library FAQs
for a detailed description of the complex build process.)

For Node.js security releases, Debian-based node images may be published in advance
of Alpine-based images. To build an Alpine-based node image requires
a musl build. This may not initially be ready at Node.js release time.
When processing non-security Node.js releases, the build process will wait for
the musl build before proceeding with Debian- and Alpine-based images.

License

License information for
the software contained in this image. License information for the
Node.js Docker project.

Supported Docker versions

If you are using Docker Desktop,
it is recommended to use a recent version, released in the last six months.

Refer to Docker Engine release notes
for current Engine versions.

Supported Node.js versions

Support for node Docker images is limited to
Node.js active versions.

Before opening an issue in this repo, please consider if the problem only occurs
in a node Docker environment.

If a problem can also be reproduced without using an image from this repo,
for example in a non-Docker environment,
then it should be reported to the corresponding component.

Use the
Node.js issues or the
npm issues list to check for known issues
or to report new issues for these components.

Supported architectures

node images are built for the Linux operating system and architecture combinations defined in versions.json.

Each of the architectures for Debian images belong to the Node.js support tier 1 or 2, recommended for production applications.

musl builds for Alpine

musl builds for amd64 are listed under support tier "Experimental" and are tested by the Node.js build process before being used in Docker images. "Experimental" status for Node.js is defined as:

Experimental: May not compile or test suite may not pass. The core team does not create releases for these platforms. Test failures on experimental platforms do not block releases. Contributions to improve support for these platforms are welcome.

musl builds for other architectures, including arm64, are not tested before release.

Yarn v1 Classic bundling

The Yarn v1 Classic package manager is bundled in node image
variants that include Node.js versions 25 and below.

Yarn v1 is not bundled into node images as of Node.js 26.0.0.
This version of the Yarn package manager has been declared as frozen and is no longer maintained.

Users with legacy requirements for Yarn v1 under Node.js 26 and above may be able
to follow Yarn v1 installation instructions
and install using npm install yarn.

Governance and Current Members

The Node.js Docker Image is governed by an open maintainer model. See
GOVERNANCE.md
for project roles and decision-making, and CONTRIBUTING.md for contribution guidance. If a final decision cannot be reached using consensus seeking, the Node.js TSC is the final arbiter.

Docker Maintainers

Collaborators

Collaborators are managed via the
@nodejs/docker team.

Emeritus


File: docs/BestPractices.md

Docker and Node.js Best Practices

Table of Contents

Environment Variables

Run with NODE_ENV set to production. This is the way you would pass in secrets and other runtime configurations to your application as well.

text
-e "NODE_ENV=production"

Upgrading npm

Each node Docker image includes npm, bundled with Node.js.
You can check the version from the CLI, for example:

shell
docker run --rm --entrypoint npm node:lts --version

The bundled npm version is also listed in the detail information on the
Node.js Releases page.
If you need to upgrade (or downgrade) the version of npm,
add the following to your Dockerfile, replacing <version> with the desired value.
View the npm registry listing for available versions and tags.

dockerfile
RUN npm install npm@<version>

Global npm dependencies

If you need to install global npm dependencies, it is recommended to place those dependencies in the non-root user directory. To achieve this, add the following line to your Dockerfile

dockerfile
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global

ENV PATH=$PATH:/home/node/.npm-global/bin # optionally if you want to run npm global bin without specifying path

This recommendation does not apply to npm itself, which is installed in /usr/local/bin/npm.

Handling Kernel Signals

Node.js was not designed to run as PID 1 which leads to unexpected behaviour when running inside of Docker. For example, a Node.js process running as PID 1 will not respond to SIGINT (CTRL-C) and similar signals. As of Docker 1.13, you can use the --init flag to wrap your Node.js process with a lightweight init system that properly handles running as PID 1.

text
docker run -it --init node

You can also include Tini directly in your Dockerfile, ensuring your process is always started with an init wrapper.

Non-root User

By default, Docker runs commands inside the container as root which violates the Principle of Least Privilege (PoLP) when superuser permissions are not strictly required. You want to run the container as an unprivileged user whenever possible. The node images provide the node user with uid 1000 for such purpose. The Docker Image can then be run with the node user in the following way:

text
-u "node"

Alternatively, the user can be activated in the Dockerfile:

dockerfile
FROM node:6.10.3
...
# At the end, set the user to use when running this image
USER 1000  # node

Note that the node user is neither a build-time nor a run-time dependency and it can be removed or altered, as long as the functionality of the application you want to add to the container does not depend on it.

If you do not want nor need the user created in this image, you can remove it with the following:

dockerfile
# For debian based images use:
RUN userdel -r node

# For alpine based images use:
RUN deluser --remove-home node

If you need to change the uid/gid of the user, you can use:

dockerfile
RUN groupmod -g 999 node && usermod -u 999 -g 999 node

If you need another name for the user (ex. myapp), execute:

dockerfile
RUN usermod -d /home/myapp -l myapp node

For alpine based images, you do not have groupmod nor usermod, so to change the uid/gid you have to delete the previous user:

dockerfile
RUN deluser --remove-home node \
  && addgroup -S node -g 999 \
  && adduser -S -G node -u 999 node

Memory

By default, any Docker Container may consume as much of the hardware such as CPU and RAM. If you are running multiple containers on the same host, you should limit how much memory they can consume.

text
-m "300M" --memory-swap "1G"

CMD

When creating an image, you can bypass the package.json's start command and bake it directly into the image itself. First off, this reduces the number of processes running inside of your container. Secondly, it causes exit signals such as SIGTERM and SIGINT to be received by the Node.js process instead of npm swallowing them.

dockerfile
CMD ["node","index.js"]

Docker Run

Here is an example of how you would run a default Node.JS Docker Containerized application:

text
$ docker run \
  --init \
  -e "NODE_ENV=production" \
  -u "node" \
  -m "300M" --memory-swap "1G" \
  -w "/home/node/app" \
  --name "my-nodejs-app" \
  node [script]

Security

The Docker team has provided a tool to analyze your running containers for potential security issues. You can download and run this tool from here: https://github.com/docker/docker-bench-security

node-gyp alpine

Here is an example of how you would install dependencies for packages that require node-gyp support on the alpine variant:

dockerfile
FROM node:alpine

RUN apk add --no-cache --virtual .gyp python3 py-setuptools make g++ \
    && npm install [ your npm dependencies here ] \
    && apk del .gyp

And, here's a multistage build example:

dockerfile
FROM node:alpine as builder

## Install build toolchain, install node deps and compile native add-ons
RUN apk add --no-cache python3 make g++
RUN npm install [ your npm dependencies here ]

FROM node:alpine as app

## Copy built node modules and binaries without including the toolchain
COPY --from=builder node_modules .

Smaller images without npm/yarn

To remove npm and Yarn package managers, use a multi-stage build.
In the first stage, the package manager builds the app.
In the second stage, the app and the node directories are copied,
without copying the npm & Yarn package managers.
In Docker images based on Node.js >=26, Yarn is already removed.

The result is a smaller and hardened final image with no package managers.

The examples below build with npm.

Alpine example

dockerfile
ARG ALPINE_VERSION=3.23

FROM node:24-alpine${ALPINE_VERSION} AS builder
WORKDIR /build-stage
COPY package*.json ./
RUN npm ci
# Copy the files you need
COPY . ./
RUN npm run build

FROM alpine:${ALPINE_VERSION}
# Create app directory
WORKDIR /usr/src/app
# Add required binaries
RUN apk add --no-cache libstdc++ dumb-init \
  && addgroup -g 1000 node && adduser -u 1000 -G node -s /bin/sh -D node \
  && chown node:node ./
COPY --from=builder /usr/local/bin/node /usr/local/bin/
COPY --from=builder /usr/local/bin/docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
USER node
# Update the following COPY lines based on your codebase
COPY --from=builder /build-stage/node_modules ./node_modules
COPY --from=builder /build-stage/dist ./dist
# Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1
CMD ["dumb-init", "node", "dist/index.js"]

Debian example

dockerfile
FROM node:24-trixie-slim AS builder
WORKDIR /build-stage
COPY package*.json ./
RUN npm ci
# Copy the files you need
COPY . ./
RUN npm run build

FROM debian:trixie-slim
# Create app directory
WORKDIR /usr/src/app
# Add required binaries
RUN apt-get update && apt-get install -y --no-install-recommends dumb-init \
    && rm -rf /var/lib/apt/lists/* \
    && groupadd --gid 1000 node \
    && useradd --uid 1000 --gid node --shell /bin/bash --create-home node \
    && chown node:node ./
COPY --from=builder /usr/local/bin/node /usr/local/bin/
COPY --from=builder /usr/local/bin/docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
USER node
# Update the following COPY lines based on your codebase
COPY --from=builder /build-stage/node_modules ./node_modules
COPY --from=builder /build-stage/dist ./dist
# Run with dumb-init to not start node with PID=1, since Node.js was not designed to run as PID 1
CMD ["dumb-init", "node", "dist/index.js"]

2. Official Technical Reference & Guides (nodejs/docs)

docs

Hi there! This repo serves as a central place for Node.js documentation
coordination, but not documentation itself. The documentation for node can be
found at http://nodejs.org/en/docs/. The source material is found in the
node core repo.

Current Documentation WG Members