Skip to main content

nodejs-containers

Node.js container optimization — Alpine, multi-stage builds, node_modules caching, BuildKit mounts (900MB to ~100MB). Use when working with Node.js containers or optimizing image sizes.

Informations de source

Dépôt
laurigates/claude-plugins
Dernière activité de la source
24 septembre 2026 à 10:45
Langue détectée de SKILL.md
anglais
Étoiles
60
Forks
6

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Explorateur de fichiers
2 fichiers

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
created
2026-01-15T00:00:00.000Z
modified
2026-09-24T00:00:00.000Z
reviewed
2026-01-15T00:00:00.000Z
name
nodejs-containers
description
Node.js container optimization — Alpine, multi-stage builds, node_modules caching, BuildKit mounts (900MB to ~100MB). Use when working with Node.js containers or optimizing image sizes.
user-invocable
false
allowed-tools
Bash, Read, Grep, Glob, Edit, Write, TodoWrite, WebSearch, WebFetch
# Node.js Container Optimization Expert knowledge for building optimized Node.js container images using Alpine variants, multi-stage builds, and Node.js-specific dependency management patterns. ## When to Use This Skill | Use this skill when... | Use `container-development` instead when... | |------------------------|---------------------------------------------| | Building Node.js-specific Dockerfiles | General multi-stage build patterns | | Optimizing Node.js image sizes | Language-agnostic container security | | Handling npm/yarn/pnpm in containers | Docker Compose configuration | | Dealing with native module builds | Non-Node.js container optimization | ## Core Expertise **Node.js Container Challenges**: - Large node_modules directories (100-500MB) - Full base images include build tools (~900MB) - Separate dev and production dependencies - Different package managers (npm, yarn, pnpm) - Native modules requiring build tools **Key Capabilities**: - Alpine-based images (~100MB vs ~900MB full) - Multi-stage builds separating build and runtime - BuildKit cache mounts for node_modules - Production-only dependency installation - Non-root user configuration ## Optimized Multi-Stage Pattern (Node Servers) The recommended pattern achieves ~100-150MB images: ```dockerfile # Dependencies stage - production only FROM node:20-alpine AS deps WORKDIR /app COPY package*.json ./ RUN npm ci --only=production # Build stage - includes devDependencies FROM node:20-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Runtime stage - minimal FROM node:20-alpine WORKDIR /app # Create non-root user RUN addgroup -g 1001 -S nodejs && \ adduser -u 1001 -S nodejs -G nodejs # Copy dependencies and built app COPY --from=deps --chown=nodejs:nodejs /app/node_modules ./node_modules COPY --from=build --chown=nodejs:nodejs /app/dist ./dist COPY --chown=nodejs:nodejs package.json ./ USER nodejs EXPOSE 3000 HEALTHCHECK --interval=30s CMD node healthcheck.js || exit 1 CMD ["node", "dist/server.js"] ``` ## BuildKit Cache Mounts (Fastest Builds) ```dockerfile # syntax=docker/dockerfile:1 FROM node:20-alpine AS build WORKDIR /app # Cache mount for npm cache RUN --mount=type=cache,target=/root/.npm \ --mount=type=bind,source=package.json,target=package.json \ --mount=type=bind,source=package-lock.json,target=package-lock.json \ npm ci COPY . . RUN npm run build FROM node:20-alpine WORKDIR /app COPY --from=build /app/dist ./dist USER node CMD ["node", "dist/server.js"] ``` **Build performance**: - First build: ~2-3 minutes - Subsequent builds (no package changes): ~10-20 seconds - Subsequent builds (package changes): ~30-60 seconds ## Package Manager Patterns ### npm ```dockerfile COPY package*.json ./ RUN npm ci --only=production RUN npm cache clean --force ``` ### yarn ```dockerfile COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile --production RUN yarn cache clean ``` ### pnpm ```dockerfile RUN npm install -g pnpm COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile --prod # pnpm creates smaller node_modules with hard links (20-30% smaller) ``` ## Next.js on Bun: build with Bun, run with Node Bun works for the dependency and build stages of a Next.js image, but the runtime stage that serves `.next/standalone` must be **Node.js**. The standalone output targets Node, and Bun does not resolve the React Server Components SSR modules it loads (`react-dom/server.edge`, `react-dom/server-rendering-stub`, `react-server-dom-webpack/client.edge`), so it fails at runtime with "Could not resolve" errors. ```dockerfile FROM oven/bun:1-debian AS deps # install FROM oven/bun:1-debian AS builder # next build FROM gcr.io/distroless/nodejs22-debian12 AS runner CMD ["server.js"] ``` ## Distroless runtime: no shell, so no `child_process` to CLI tools A distroless Node image contains Node and nothing else: no `/bin/sh`, `gzip`, `pg_dump`, or `psql`. Application code that shells out through `node:child_process` (`exec`, `execSync`, `spawn` of a CLI) works in local dev and fails only in production, with `spawn /bin/sh ENOENT`. Use Node built-ins or a library instead: | Shell tool | In-process replacement | |------------|------------------------| | `gzip` / `gunzip` | `node:zlib` (`gzipSync`, `createGzip`, `gunzipSync`) | | `cat`, `cp`, file writes | `node:fs` | | `pg_dump` / `psql` | export/import through the app's database client or ORM | The same constraint means ops scripts cannot be `kubectl exec`'d into the running app pod. Ship them in a separate image and run them as a Job. To stop the mistake before review, ban the import with a lint rule (for example Biome `noRestrictedImports` on `node:child_process` for server source). ## Performance Impact | Metric | Full Node (900MB) | Alpine (350MB) | Multi-Stage (100MB) | Improvement | |--------|-------------------|----------------|---------------------|-------------| | **Image Size** | 900MB | 350MB | 100MB | 89% reduction | | **Pull Time** | 3m 20s | 1m 10s | 25s | 87% faster | | **Build Time** | 4m 30s | 3m 15s | 2m 30s | 44% faster | | **Rebuild (cached)** | 2m 10s | 1m 30s | 15s | 88% faster | | **Memory Usage** | 512MB | 256MB | 180MB | 65% reduction | ## Security Impact | Image Type | Vulnerabilities | Size | Risk | |------------|-----------------|------|------| | **node:20 (Debian)** | 45-60 CVEs | 900MB | High | | **node:20-alpine** | 8-12 CVEs | 350MB | Medium | | **Multi-stage Alpine** | 4-8 CVEs | 100MB | Low | | **Distroless Node** | 2-4 CVEs | 120MB | Very Low | ## Agentic Optimizations | Context | Command | Purpose | |---------|---------|---------| | **Fast rebuild** | `DOCKER_BUILDKIT=1 docker build --target build .` | Build only build stage | | **Size check** | `docker images app --format "table {{.Repository}}\t{{.Size}}"` | Compare sizes | | **Layer analysis** | `docker history app:latest --human --no-trunc \| head -20` | Find large layers | | **Dependency audit** | `docker run --rm app npm audit --production` | Check vulnerabilities | | **Cache clear** | `docker builder prune --filter type=exec.cachemount` | Clear BuildKit cache | | **Test locally** | `docker run --rm -p 3000:3000 app` | Quick local test | ## Best Practices - Use Alpine variants for smaller images - Use `npm ci` not `npm install` (reproducible builds) - Separate dev and production dependencies - Run as non-root user - Use multi-stage builds for production - Layer package.json separately from source code - Add .dockerignore to exclude node_modules, tests For detailed examples, advanced patterns, and best practices, see [REFERENCE.md](REFERENCE.md). ## Related Skills - `container-development` - General container patterns, multi-stage builds, security - `go-containers` - Go-specific container optimizations - `python-containers` - Python-specific container optimizations
Voir sur GitHub