--- title: Node.js description: Migrate a Node.js application to Docker Hardened Images weight: 30 keywords: nodejs, node, migration, dhi --- 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) > [!NOTE] > > Multi-stage builds are recommended for most use cases. Single-stage builds are > supported for simplicity, but come with tradeoffs in size and security. > > You must authenticate to `dhi.io` before you can pull Docker Hardened Images. > Use your Docker ID credentials (the same username and password you use for > Docker Hub). If you don't have a Docker account, [create > one](../../../accounts/create-account.md) for free. > > Run `docker login dhi.io` to authenticate. {{< tabs >}} {{< tab name="Before (Ubuntu)" >}} ```dockerfile #syntax=docker/dockerfile:1 FROM ubuntu/node:18-24.04_edge WORKDIR /usr/src/app COPY package*.json ./ RUN npm install COPY . . CMD ["node", "index.js"] ``` {{< /tab >}} {{< tab name="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 ["node", "index.js"] ``` {{< /tab >}} {{< tab name="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 && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/* RUN npm install COPY . . CMD ["node", "index.js"] ``` {{< /tab >}} {{< tab name="After (multi-stage)" >}} ```dockerfile #syntax=docker/dockerfile:1 # === Build stage: Install dependencies and build application === FROM dhi.io/node:23-alpine3.21-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:23-alpine3.21 ENV PATH=/app/node_modules/.bin:$PATH COPY --from=builder --chown=node:node /usr/src/app /app WORKDIR /app CMD ["index.js"] ``` {{< /tab >}} {{< tab name="After (single-stage)" >}} ```dockerfile #syntax=docker/dockerfile:1 FROM dhi.io/node:23-alpine3.21-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"] ``` {{< /tab >}} {{< /tabs >}}