jpskill.com
🛠️ 開発・MCP コミュニティ

infra-ci-cd-docker

Node.js/TypeScriptで開発したアプリケーションを、Dockerを使って効率的にコンテナ化し、開発から本番環境への移行をスムーズにするためのパターンを提案するSkill。

📜 元の英語説明(参考)

Docker containerization patterns for Node.js/TypeScript development and production

🇯🇵 日本人クリエイター向け解説

一言でいうと

Node.js/TypeScriptで開発したアプリケーションを、Dockerを使って効率的にコンテナ化し、開発から本番環境への移行をスムーズにするためのパターンを提案するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o infra-ci-cd-docker.zip https://jpskill.com/download/10252.zip && unzip -o infra-ci-cd-docker.zip && rm infra-ci-cd-docker.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10252.zip -OutFile "$d\infra-ci-cd-docker.zip"; Expand-Archive "$d\infra-ci-cd-docker.zip" -DestinationPath $d -Force; ri "$d\infra-ci-cd-docker.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して infra-ci-cd-docker.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → infra-ci-cd-docker フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Docker コンテナ化のパターン

クイックガイド: Node.js/TypeScript アプリケーションをコンテナ化するための BuildKit を使用した Docker。最小限のプロダクションイメージ(1GB から 100MB 未満)のためのマルチステージビルド。開発環境のための Docker Compose v2。依存関係のインストールを 10 倍高速化する BuildKit キャッシュマウント。プロダクションセキュリティのための非 root ユーザー、ヘルスチェック、およびシークレットマウント。サイズを小さくするための Alpine、互換性のための Debian slim。


<critical_requirements>

重要: この Skill を使用する前に

すべてのコードは CLAUDE.md のプロジェクト規約に従う必要があります (kebab-case、名前付きエクスポート、インポート順序、import type、名前付き定数)

(プロダクションイメージには必ずマルチステージビルドを使用してください - 開発依存関係、TypeScript コンパイラ、またはソースファイルをプロダクションに出荷しないでください)

(コンテナは必ず非 root ユーザーとして実行してください - プロダクションコンテナを root (デフォルト) として実行しないでください)

(必ず CMD ["node", "server.js"] (exec 形式) を使用してください - npm start またはシェル形式を CMD として使用しないでください)

(ビルド時に機密データには必ず BuildKit シークレットマウントを使用してください - シークレットに ARG または ENV を使用しないでください)

(ソースコードの前に package.json/lockfile をコピーしてください - npm ci の前に COPY . . をしないでください (レイヤーキャッシュが壊れます))

</critical_requirements>



自動検出: Dockerfile, docker-compose, compose.yaml, Docker, container, multi-stage build, BuildKit, .dockerignore, Docker Compose, docker build, docker run, HEALTHCHECK, Docker Scout, docker init, containerize, container image, Docker network, Docker volume

いつ使うか:

  • Node.js/TypeScript アプリケーション用の Dockerfile を作成する場合
  • プロダクションイメージのサイズを最小限に抑えるために、マルチステージビルドをセットアップする場合
  • ローカル開発環境のために Docker Compose を構成する場合
  • Docker レイヤーキャッシュと BuildKit キャッシュマウントを最適化する場合
  • コンテナセキュリティを実装する場合 (非 root、シークレット、読み取り専用ファイルシステム)
  • コンテナオーケストレーションのためにヘルスチェックをセットアップする場合
  • Docker イメージをビルドしてプッシュする CI/CD パイプラインを構築する場合
  • OS プラットフォーム全体で一貫した開発環境を必要とするチーム
  • 依存関係を持つ分離されたサービスを必要とするマイクロサービスアーキテクチャ

いつ使わないか:

  • コンテナを使用しないサーバーレスデプロイメント (AWS Lambda, Vercel Functions)
  • サーバーランタイムのない静的サイトホスティング (Netlify, Vercel, Cloudflare Pages)
  • npm 経由で配布される単純なスクリプトまたは CLI ツール
  • コンテナ化の要件がないローカル開発
  • 追加された複雑さが分離の利点を上回る場合
  • Kubernetes 固有のオーケストレーションパターン (Kubernetes の Skill を使用してください)

カバーされる主なパターン:

  • Node.js/TypeScript 用のマルチステージ Dockerfile (ビルダーパターン)
  • Docker Compose v2 開発環境
  • BuildKit キャッシュマウントとレイヤーの最適化
  • コンテナセキュリティ (非 root、シークレット、ケーパビリティ、読み取り専用)
  • プロダクションコンテナのヘルスチェック
  • ビルドコンテキストの最適化のための .dockerignore
  • ボリュームマウント (名前付きボリューム、バインドマウント、tmpfs)
  • Docker ネットワーク (bridge, host, overlay)
  • CI/CD 統合 (GitHub Actions build-push)
  • シグナルハンドリング (graceful shutdown 用の tini)

<philosophy>

哲学

コンテナは、「私のマシンでは動く」問題を排除する、再現可能で分離された環境を提供します。 Docker は、Node.js/TypeScript アプリケーションを移植可能で軽量なイメージにパッケージ化するための標準です。

コア原則:

  1. 最小限のプロダクションイメージ - アプリの実行に必要なものだけを出荷します (コンパイルされた JS、プロダクション依存関係、ランタイム)
  2. レイヤーキャッシュの最適化 - 変更されていないレイヤーが再利用されるように Dockerfile を構造化し、リビルドを高速化します
  3. デフォルトによるセキュリティ - 非 root ユーザー、イメージにシークレットを含めない、最小限の攻撃対象領域
  4. 開発のパリティ - Docker Compose はローカルでプロダクショントポロジをミラーリングします

</philosophy>


<patterns>

コアパターン

パターン 1: Node.js/TypeScript 用のマルチステージ Dockerfile

マルチステージビルドは、ビルダー段階で TypeScript をコンパイルし、コンパイルされた JS とプロダクション依存関係のみを最小限のランタイムイメージにコピーします。これにより、イメージが 1GB 以上から 100MB 未満に削減されます。

プロダクション Dockerfile は 3 つのステージを使用します。

  1. deps - プロダクション依存関係のみをインストールします
  2. builder - すべての依存関係をインストールし、TypeScript をコンパイルします
  3. runner - コンパイルされた出力とプロダクション依存関係を最小限のイメージにコピーします
# Stage 1: Production dependencies
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev --no-audit --no-fund

# Stage 2: Build TypeScript
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci --no-audit --no-fund
COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build

# Stage 3: Production runtime
FROM node:22-alpine AS runner
WORKDIR /app
RUN apk add --no-cache tini
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 appgroup && \
    adduser --system --uid 1001 --ingroup appgroup appuser
COPY --from=deps --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --chown=appuser:appgroup package.json ./
USER appuser
EXPOSE 3000
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "dist/server.js"]

良い理由: 3 段階ビルドは関心を分離し、BuildKit キャッシュマウントは npm ci を高速化し、非 root ユーザー、シグナルハンドリング用の tini、最終イメージにはプロダクションアーティファクトのみが含まれます

Bun およびモノレポバリアントを含む完全な Dockerfile については、examples/core.md を参照してください。


パターン 2: Docker Compos

(原文がここで切り詰められています)

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Docker Containerization Patterns

Quick Guide: Docker with BuildKit for containerizing Node.js/TypeScript applications. Multi-stage builds for minimal production images (1GB to under 100MB). Docker Compose v2 for development environments. BuildKit cache mounts for 10x faster dependency installs. Non-root users, health checks, and secret mounts for production security. Alpine for size, Debian slim for compatibility.


<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST use multi-stage builds for production images - NEVER ship dev dependencies, TypeScript compiler, or source files in production)

(You MUST run containers as non-root user - NEVER run production containers as root (default))

(You MUST use CMD ["node", "server.js"] (exec form) - NEVER use npm start or shell form as CMD)

(You MUST use BuildKit secret mounts for sensitive data at build time - NEVER use ARG or ENV for secrets)

(You MUST copy package.json/lockfile BEFORE source code - NEVER COPY . . before npm ci (breaks layer cache))

</critical_requirements>


Examples

  • Dockerfile Patterns - Multi-stage builds, Bun, monorepo, layer caching, .dockerignore, signal handling
  • Docker Compose - Development environments, networking, volumes, healthchecks
  • Production & CI/CD - Security hardening, secrets, CI/CD pipelines, vulnerability scanning
  • Quick Reference - Dockerfile instructions, CLI commands, base image comparison

Auto-detection: Dockerfile, docker-compose, compose.yaml, Docker, container, multi-stage build, BuildKit, .dockerignore, Docker Compose, docker build, docker run, HEALTHCHECK, Docker Scout, docker init, containerize, container image, Docker network, Docker volume

When to use:

  • Creating Dockerfiles for Node.js/TypeScript applications
  • Setting up multi-stage builds to minimize production image size
  • Configuring Docker Compose for local development environments
  • Optimizing Docker layer caching and BuildKit cache mounts
  • Implementing container security (non-root, secrets, read-only filesystem)
  • Setting up health checks for container orchestration
  • Building CI/CD pipelines that build and push Docker images
  • Teams needing consistent development environments across OS platforms
  • Microservice architectures requiring isolated services with dependencies

When NOT to use:

  • Serverless deployments (AWS Lambda, Vercel Functions) that don't use containers
  • Static site hosting (Netlify, Vercel, Cloudflare Pages) with no server runtime
  • Simple scripts or CLI tools distributed via npm
  • Local development without containerization requirements
  • When added complexity outweighs the isolation benefit
  • Kubernetes-specific orchestration patterns (use a Kubernetes skill)

Key patterns covered:

  • Multi-stage Dockerfile for Node.js/TypeScript (builder pattern)
  • Docker Compose v2 development environments
  • BuildKit cache mounts and layer optimization
  • Container security (non-root, secrets, capabilities, read-only)
  • Health checks for production containers
  • .dockerignore for build context optimization
  • Volume mounts (named volumes, bind mounts, tmpfs)
  • Docker networking (bridge, host, overlay)
  • CI/CD integration (GitHub Actions build-push)
  • Signal handling (tini for graceful shutdown)

<philosophy>

Philosophy

Containers provide reproducible, isolated environments that eliminate "works on my machine" problems. Docker is the standard for packaging Node.js/TypeScript applications into portable, lightweight images.

Core principles:

  1. Minimal production images - Ship only what the app needs to run (compiled JS, production deps, runtime)
  2. Layer cache optimization - Structure Dockerfiles so unchanged layers are reused, making rebuilds fast
  3. Security by default - Non-root users, no secrets in images, minimal attack surface
  4. Development parity - Docker Compose mirrors production topology locally

</philosophy>


<patterns>

Core Patterns

Pattern 1: Multi-Stage Dockerfile for Node.js/TypeScript

Multi-stage builds compile TypeScript in a builder stage, then copy only compiled JS and production dependencies into a minimal runtime image. This reduces images from 1GB+ to under 100MB.

A production Dockerfile uses three stages:

  1. deps - Install production dependencies only
  2. builder - Install all dependencies, compile TypeScript
  3. runner - Copy compiled output and production deps into minimal image
# Stage 1: Production dependencies
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev --no-audit --no-fund

# Stage 2: Build TypeScript
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci --no-audit --no-fund
COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build

# Stage 3: Production runtime
FROM node:22-alpine AS runner
WORKDIR /app
RUN apk add --no-cache tini
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 appgroup && \
    adduser --system --uid 1001 --ingroup appgroup appuser
COPY --from=deps --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --chown=appuser:appgroup package.json ./
USER appuser
EXPOSE 3000
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "dist/server.js"]

Why good: Three-stage build separates concerns, BuildKit cache mount speeds up npm ci, non-root user, tini for signal handling, only production artifacts in final image

See examples/core.md for complete Dockerfiles including Bun and monorepo variants.


Pattern 2: Docker Compose for Development

Docker Compose v2 defines multi-container development environments. Use compose.yaml (not docker-compose.yml) with the docker compose command (no hyphen).

# compose.yaml
services:
  app:
    build:
      context: .
      target: builder
    volumes:
      - .:/app:cached
      - /app/node_modules
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:17-alpine
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dev"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

Why good: Health checks on dependencies with condition: service_healthy, bind mount with :cached for macOS perf, anonymous volume protects node_modules, named volume for database persistence

See examples/compose.md for full development environments with Redis, networking, and volume patterns.


Pattern 3: BuildKit Cache Mounts

BuildKit (default since Docker Engine 23+) provides cache mounts that persist package manager caches across builds, reducing install times by 10x or more.

# npm
RUN --mount=type=cache,target=/root/.npm \
    npm ci --no-audit --no-fund

# pnpm
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
    pnpm install --frozen-lockfile

Layer ordering rules: Pin base image versions > Copy dependency manifests > Install dependencies > Copy source code > Build/compile. This maximizes cache hits.

See examples/core.md for cache mount patterns for npm, Bun, pnpm, and apt.


Pattern 4: Container Security

Non-Root User

RUN addgroup --system --gid 1001 appgroup && \
    adduser --system --uid 1001 --ingroup appgroup appuser
COPY --chown=appuser:appgroup --from=builder /app/dist ./dist
USER appuser

Secret Mounts (Build Time)

# Secret is ephemeral - never persisted in image layers
RUN --mount=type=secret,id=npm_token,env=NPM_TOKEN \
    npm ci --no-audit --no-fund
# Build: docker build --secret id=npm_token,env=NPM_TOKEN .

Runtime Hardening

services:
  app:
    read_only: true
    tmpfs: [/tmp]
    security_opt: [no-new-privileges:true]
    cap_drop: [ALL]

See examples/production.md for complete production compose, secrets management, and CI/CD pipelines.


Pattern 5: Health Checks

Health checks enable orchestrators to detect unresponsive containers and restart them automatically.

HEALTHCHECK --interval=30s --timeout=10s --retries=3 --start-period=30s \
    CMD ["node", "-e", "fetch('http://localhost:3000/health').then(r => { if (!r.ok) process.exit(1) }).catch(() => process.exit(1))"]

Why good: Uses Node.js built-in fetch (no curl needed in Alpine), start-period allows app startup, checks dedicated health endpoint not just root path

See examples/production.md for health check endpoint implementation and Compose healthcheck patterns.


Pattern 6: .dockerignore

node_modules
dist
.git
.env
.env.*
!.env.example
Dockerfile*
compose.yaml
__tests__
*.test.ts
coverage
.github

Why good: Excludes node_modules (reinstalled deterministically), .env files (prevents secret leaks), .git (invalidates cache), keeps build context small

See examples/core.md for a comprehensive .dockerignore file.


Pattern 7: Signal Handling and Graceful Shutdown

Node.js as PID 1 does not handle SIGTERM/SIGINT correctly. Use tini as init system.

RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "dist/server.js"]

Why good: Tini forwards signals to node process, handles zombie process reaping, ensures graceful shutdown on docker stop

See examples/core.md for complete TypeScript graceful shutdown implementation.

</patterns>


<performance>

Performance Optimization

Image Size Reduction

Technique Impact
Multi-stage builds 1GB to under 100MB (90%+ reduction)
Alpine base image 135MB vs 1GB (full) vs 200MB (slim)
npm ci --omit=dev Removes dev dependencies from production
.dockerignore Smaller build context, faster sends

Build Speed Optimization

Technique Impact
BuildKit cache mounts 10x faster dependency installs
Layer ordering (deps before source) Cache hit on source-only changes
.dockerignore excluding node_modules Prevents sending GBs to daemon
--no-audit --no-fund flags Skip unnecessary npm checks
Parallel multi-stage builds BuildKit builds independent stages concurrently

CI/CD Build Cache

# GitHub Actions - Cache Docker layers
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v7
  with:
    cache-from: type=gha
    cache-to: type=gha,mode=max

Why good: GitHub Actions cache (type=gha) persists layers across CI runs, mode=max caches all layers (not just final)

See examples/production.md for complete CI/CD pipeline examples.

</performance>


<decision_framework>

Decision Framework

Base Image Selection

Which base image?
  |
  +-- Need smallest image? --> Alpine (node:22-alpine, ~135MB)
  |     +-- musl libc compatibility issues? --> Use Debian slim instead
  |
  +-- Need maximum compatibility? --> Debian slim (node:22-slim, ~200MB)
  |     +-- Native extensions work out of the box
  |
  +-- Need debugging tools? --> Full image (node:22, ~1GB)
  |     +-- Development only, never for production
  |
  +-- Maximum security? --> Distroless (gcr.io/distroless/nodejs22-debian12)
        +-- No shell, no package manager, smallest attack surface

Compose vs Dockerfile Targets

How to manage dev vs prod?
  |
  +-- Multi-stage Dockerfile with targets
  |     +-- `docker compose build --target builder` for dev
  |     +-- Final stage for production
  |
  +-- Separate compose files
        +-- compose.yaml (base)
        +-- compose.override.yaml (dev - auto-loaded)
        +-- compose.prod.yaml (production)

Volume Strategy

What data needs to persist?
  |
  +-- Source code (dev hot reload) --> Bind mount with :cached
  +-- Database files --> Named volume
  +-- Temporary/cache data --> tmpfs
  +-- Secrets at runtime --> Docker secrets or tmpfs
  +-- node_modules in dev --> Anonymous volume (protect from host)

</decision_framework>


<integration>

Integration Guide

Docker ecosystem tools:

  • Docker Scout: docker scout cves for vulnerability scanning in CLI and CI
  • BuildKit: Default build engine since Docker Engine 23+, enables cache mounts, secret mounts, multi-platform builds

CI/CD integration:

Docker images integrate with any CI/CD pipeline. See examples/production.md for build-push patterns and vulnerability scanning workflows.

Container orchestration:

Production images work with any container orchestrator. Health checks (HEALTHCHECK instruction) and non-root users are universally required regardless of platform.

Replaces:

  • VM-based development environments (Docker Compose provides lighter isolation)
  • Manual server provisioning (Dockerfiles codify environment setup)
  • Node version managers in containers (Dockerfile pins exact Node version via base image tag)

</integration>


<red_flags>

RED FLAGS

High Priority Issues:

  • Running production containers as root (default behavior - always add USER directive)
  • Secrets in ARG/ENV/COPY (persist in image layers - use --mount=type=secret)
  • Single-stage builds shipping dev dependencies and source code to production
  • Using npm start as CMD (npm swallows SIGTERM - use CMD ["node", "dist/server.js"])
  • No .dockerignore file (node_modules sent to daemon, secrets leaked into image)
  • Using :latest tag for base images (non-deterministic builds)

Medium Priority Issues:

  • COPY . . before npm ci (any file change invalidates dependency cache)
  • No health check defined (orchestrator cannot detect unresponsive containers)
  • docker-compose.yml with version: key (deprecated - use compose.yaml without version)
  • depends_on without condition: service_healthy (container starts before dependency is ready)
  • Using npm install instead of npm ci in Dockerfile (non-deterministic, slower)

Common Mistakes:

  • Forgetting anonymous volume for node_modules in dev (/app/node_modules) causing host to overwrite container's modules
  • Not using :cached on bind mounts on macOS (significant performance impact)
  • Installing build tools (gcc, make, python) in the final stage instead of the builder stage
  • Exposing database ports to host in production Compose (only needed for dev)

Gotchas & Edge Cases:

  • Alpine uses musl libc - some npm packages with native C bindings (bcrypt, sharp, canvas) may fail; use npm rebuild or switch to Debian slim
  • Node.js fetch() is available since Node 18+ (no need for curl in health checks on Alpine)
  • BuildKit cache mounts require # syntax=docker/dockerfile:1 or Docker Engine 23+ with BuildKit enabled by default
  • docker compose down -v removes named volumes (data loss) - use docker compose down without -v to preserve data
  • Docker Desktop on macOS/Windows has different file system performance than Linux - bind mounts are slower
  • COPY --chown is more efficient than COPY + RUN chown (one layer vs two)
  • tini must be installed explicitly on Alpine (apk add --no-cache tini) - it is NOT included by default in node:alpine images
  • The node_modules/.cache directory can grow large in development - add it to .dockerignore

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST use multi-stage builds for production images - NEVER ship dev dependencies, TypeScript compiler, or source files in production)

(You MUST run containers as non-root user - NEVER run production containers as root (default))

(You MUST use CMD ["node", "server.js"] (exec form) - NEVER use npm start or shell form as CMD)

(You MUST use BuildKit secret mounts for sensitive data at build time - NEVER use ARG or ENV for secrets)

(You MUST copy package.json/lockfile BEFORE source code - NEVER COPY . . before npm ci (breaks layer cache))

Failure to follow these rules will result in bloated images (1GB+), security vulnerabilities (root access, leaked secrets), broken graceful shutdown (lost requests on deploy), and slow CI builds (no layer caching).

</critical_reminders>