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本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
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
$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. 下の青いボタンを押して
infra-ci-cd-docker.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
infra-ci-cd-dockerフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
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 のパターン - マルチステージビルド、Bun、モノレポ、レイヤーキャッシュ、.dockerignore、シグナルハンドリング
- Docker Compose - 開発環境、ネットワーク、ボリューム、ヘルスチェック
- プロダクション & CI/CD - セキュリティ強化、シークレット、CI/CD パイプライン、脆弱性スキャン
- クイックリファレンス - Dockerfile 命令、CLI コマンド、ベースイメージの比較
自動検出: 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 アプリケーションを移植可能で軽量なイメージにパッケージ化するための標準です。
コア原則:
- 最小限のプロダクションイメージ - アプリの実行に必要なものだけを出荷します (コンパイルされた JS、プロダクション依存関係、ランタイム)
- レイヤーキャッシュの最適化 - 変更されていないレイヤーが再利用されるように Dockerfile を構造化し、リビルドを高速化します
- デフォルトによるセキュリティ - 非 root ユーザー、イメージにシークレットを含めない、最小限の攻撃対象領域
- 開発のパリティ - Docker Compose はローカルでプロダクショントポロジをミラーリングします
</philosophy>
<patterns>
コアパターン
パターン 1: Node.js/TypeScript 用のマルチステージ Dockerfile
マルチステージビルドは、ビルダー段階で TypeScript をコンパイルし、コンパイルされた JS とプロダクション依存関係のみを最小限のランタイムイメージにコピーします。これにより、イメージが 1GB 以上から 100MB 未満に削減されます。
プロダクション Dockerfile は 3 つのステージを使用します。
- deps - プロダクション依存関係のみをインストールします
- builder - すべての依存関係をインストールし、TypeScript をコンパイルします
- 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
.dockerignorefor 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:
- Minimal production images - Ship only what the app needs to run (compiled JS, production deps, runtime)
- Layer cache optimization - Structure Dockerfiles so unchanged layers are reused, making rebuilds fast
- Security by default - Non-root users, no secrets in images, minimal attack surface
- 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:
- deps - Install production dependencies only
- builder - Install all dependencies, compile TypeScript
- 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 cvesfor 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 startas CMD (npm swallows SIGTERM - useCMD ["node", "dist/server.js"]) - No
.dockerignorefile (node_modules sent to daemon, secrets leaked into image) - Using
:latesttag for base images (non-deterministic builds)
Medium Priority Issues:
COPY . .beforenpm ci(any file change invalidates dependency cache)- No health check defined (orchestrator cannot detect unresponsive containers)
docker-compose.ymlwithversion:key (deprecated - usecompose.yamlwithout version)depends_onwithoutcondition: service_healthy(container starts before dependency is ready)- Using
npm installinstead ofnpm ciin 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
:cachedon 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 rebuildor 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:1or Docker Engine 23+ with BuildKit enabled by default docker compose down -vremoves named volumes (data loss) - usedocker compose downwithout-vto preserve data- Docker Desktop on macOS/Windows has different file system performance than Linux - bind mounts are slower
COPY --chownis more efficient thanCOPY+RUN chown(one layer vs two)tinimust be installed explicitly on Alpine (apk add --no-cache tini) - it is NOT included by default innode:alpineimages- The
node_modules/.cachedirectory 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>