Infra ci cd docker
Skill agents-inc/skills/dist/plugins/infra-ci-cd-docker/skills/infra-ci-cd-docker
The official skills marketplace for Agents Inc, an agent composition framework that builds stacks and compiles specialized subagents for Claude Code
npx -y skills add agents-inc/skills --skill infra-ci-cd-dockerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 18 stars18 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Docker containerization patterns for Node.js/TypeScript development and production
SKILL.md
16.9 KB, as published. Nobody here has run it
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
<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)
<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>