Detection

migetpacks detects Node.js when any of these files are present in your project root:
  • package.json
  • package-lock.json
  • yarn.lock
  • pnpm-lock.yaml

Package Manager Detection

The package manager is detected from lockfiles first, then from the packageManager field in package.json:
PrioritySignalResult
1pnpm-lock.yaml existspnpm
2yarn.lock existsyarn
3package-lock.json existsnpm
4packageManager field in package.jsonnpm, yarn, or pnpm
5package.json exists (no lockfile)npm
If multiple lockfiles are detected (e.g., both yarn.lock and package-lock.json), migetpacks will warn you and use the highest-priority lockfile. Remove unused lockfiles to avoid confusion.

Version Detection

Node.js version is resolved in this order:
PrioritySourceExample
1NODE_VERSION env varNODE_VERSION=20
2.node-version file22.16.0
3.nvmrc file20
4engines.node in package.json">=20"
5Default22.16.0
Version constraints are normalized for Docker compatibility:
  • 20.x becomes 20
  • >=18 becomes 18
  • ^20.0.0 becomes 20.0
  • 20.x || 22.x || 24.x becomes 24 (highest major)

Build Process

migetpacks generates a multi-stage Dockerfile optimized for layer caching:
# Builder stage
FROM node:22 AS builder
WORKDIR /build

# Layer 1: Copy dependency files (cached if lockfiles unchanged)
COPY package.json package-lock.json ./
ENV NODE_ENV=production

# Layer 2: Install dependencies (CACHED when only source code changes)
RUN npm ci

# Layer 3: Copy source code
COPY . .

# Layer 4: Build and prune
RUN npm run build \
    && npm prune --production \
    && rm -rf .git .github test tests spec __tests__ coverage .nyc_output .cache

# Runtime stage
FROM node:22-slim
WORKDIR /app
COPY --from=builder /build /app
ENV NODE_ENV=production

Package Manager Commands

ManagerInstallPrune
npmnpm ci (or npm install)npm prune --production
yarnyarn install --frozen-lockfileyarn install --production --frozen-lockfile --ignore-scripts
pnpmpnpm install --frozen-lockfilepnpm prune --prod

Build Script

If package.json contains a "build" script, it is automatically executed after dependency installation. You can override this with the BUILD_COMMAND environment variable.

Runtime Cleanup

The following directories are removed from the final image:
  • .git/, .github/
  • test/, tests/, spec/, __tests__/
  • coverage/, .nyc_output/, .cache/

Run Command

The default run command is determined in this order:
PrioritySourceCommand
1RUN_COMMAND env varUser-specified
2web: in ProcfileFrom Procfile
3scripts.start in package.jsonnpm start
4Defaultnode index.js

Caching

Docker Layer Caching

Dependencies are installed in a separate layer before source code is copied. This means npm ci is only re-run when package.json or package-lock.json changes.

BuildKit Cache Mounts

When BUILD_CACHE_DIR is configured, BuildKit cache mounts are used for package manager caches:
ManagerCache Path
npm/cache/npm
yarn/cache/yarn
pnpm/cache/pnpm

Registry Cache

Use CACHE_IMAGE to push/pull BuildKit inline cache layers to a registry for cross-build caching.

DHI Support

Node.js is fully supported with Docker Hardened Images.
StageImage
Builddhi.io/node:{version}-dev
Runtimedhi.io/node:{version}
The -dev variant includes a shell and package manager for building. The runtime image is distroless with no shell, providing a minimal attack surface.
DHI runtime images run as the node user (non-root). Commands must use exec format since there is no /bin/sh available.

Example

docker run --rm \
  -v /path/to/app:/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=my-node-app:latest \
  miget/migetpacks:latest

With Custom Options

docker run --rm \
  -v /path/to/app:/workspace/source \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e OUTPUT_IMAGE=registry.io/app:v1 \
  -e NODE_VERSION=20 \
  -e BUILD_COMMAND="npm run build:prod" \
  -e NODE_OPTIONS="--max-old-space-size=4096" \
  -e USE_DHI=true \
  miget/migetpacks:latest

Environment Variables

Any environment variable not recognized by migetpacks is automatically injected into the generated Dockerfile. Common Node.js variables:
  • NODE_OPTIONS - Node.js runtime options (e.g., --max-old-space-size=4096)
  • VITE_* - Vite build-time variables
  • NEXT_PUBLIC_* - Next.js public environment variables