All skills
simota avatar

/gear

@e307415
by shingo imotasimota/agent-skills85 stars
15

Managing dependencies, CI/CD, advanced GitHub Actions workflows, containers, secrets, and operational config. Use for build, workflow, or environment work.

Use this Skill: https://skilld.dev/gh/simota/agent-skills/gear

This session only. Nothing lands on disk.

referencedocker-patterns.md

≈4k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Docker Patterns

Dockerfile best practices, multi-stage builds, docker-compose, BuildKit optimizations, and security scanning.

Current stable lines (2026-05): Docker Engine 27.x (auto-provenance mode=min on every docker buildx build), Buildx 0.21+ (GHA cache v2 default, image-manifest enabled since BuildKit 0.21), Compose Spec 5.x "Mont Blanc" (released Dec 2025; internal builder removed in favour of Bake delegation), Docker Desktop 4.x / 5.0 (Compose-for-Kubernetes lets you deploy Compose files directly to a cluster without manual conversion). [Source: Buildx v0.21.0 release; Compose release notes; Docker Hardened Images announcement]


Multi-Stage Build (Node.js)

# syntax=docker/dockerfile:1.10
# ============================================
# Stage 1: Dependencies (pin base by digest, not tag)
# ============================================
FROM node:22-alpine@sha256:<digest> AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Copy package files
COPY package.json pnpm-lock.yaml ./
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
    corepack enable pnpm && pnpm install --frozen-lockfile

# ============================================
# Stage 2: Builder
# ============================================
FROM node:22-alpine@sha256:<digest> AS builder
WORKDIR /app

COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Build application
RUN corepack enable pnpm && pnpm build

# ============================================
# Stage 3: Production
# ============================================
FROM node:22-alpine@sha256:<digest> AS runner
WORKDIR /app

ENV NODE_ENV=production

# Security: Run as non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 appuser

# Copy only necessary files
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

USER appuser

EXPOSE 3000
ENV PORT=3000

# HEALTHCHECK helps Compose/K8s wait for readiness; cheap shallow probe
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD node -e "fetch('http://127.0.0.1:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"

CMD ["node", "dist/index.js"]

Use Node 22 LTS (active LTS through Apr 2027) or Node 24 (Oct 2026 release) — Node 20 is in maintenance from Apr 2026. Pin by digest so a hijacked tag cannot silently replace the base layer.


Next.js Optimized Dockerfile

# ============================================
# Base: Alpine with Node
# ============================================
FROM node:20-alpine AS base
RUN apk add --no-cache libc6-compat
RUN corepack enable pnpm

# ============================================
# Dependencies
# ============================================
FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

# ============================================
# Builder
# ============================================
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Disable telemetry during build
ENV NEXT_TELEMETRY_DISABLED=1

RUN pnpm build

# ============================================
# Production Runner
# ============================================
FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Copy public assets
COPY --from=builder /app/public ./public

# Set correct permissions for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next

# Copy standalone output
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"

CMD ["node", "server.js"]

Distroless / Hardened Base Images (Minimal Attack Surface)

Three production-grade hardened-base families are stable in 2026:

Family Origin License Provenance
Google Distroless Google Apache-2.0 Container Image v1
Chainguard Images (Wolfi) Chainguard Apache-2.0 (free public catalog; FIPS / extended-LTS = paid) SLSA L2, Sigstore-signed, nightly rebuilds
Docker Hardened Images (DHI) Docker Apache-2.0 (1,000+ images open-sourced 2025-12-17) SLSA L3 provenance, full SBOM, signed

DHI claims up to 95% CVE reduction vs community images; Wolfi → DHI migration is straightforward because DHI ships an Alpine-like variant. [Source: Docker — Hardened Images for Everyone; Chainguard vs Docker comparison]

# Build stage
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile
COPY . .
RUN pnpm build

# --- Production: Google Distroless ---
FROM gcr.io/distroless/nodejs22-debian12@sha256:<digest>
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER nonroot
EXPOSE 3000
CMD ["dist/index.js"]

# --- Alternative: Chainguard Wolfi (rolling, nightly CVE-patched) ---
# FROM cgr.dev/chainguard/node:latest@sha256:<digest>

# --- Alternative: Docker Hardened Image (since 2025-12) ---
# FROM dhi.docker.com/node:22-debian@sha256:<digest>

docker-compose Development

Compose v2 dropped the version: field — it has been ignored since 2023 and warns since Compose 2.30. The current schema is the Compose Specification 5.x ("Mont Blanc", Dec 2025). Always invoke as docker compose (plugin); the standalone docker-compose binary is deprecated. [Source: Compose v2 release notes; Compose Develop Spec]

# compose.yaml  (no top-level `version:` — modern spec)
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: deps  # Stop at deps stage for dev
    volumes:
      - .:/app
      - /app/node_modules  # Anonymous volume for node_modules
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    depends_on:
      db:
        condition: service_healthy
    command: pnpm dev

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d mydb"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  postgres_data:

.dockerignore

node_modules
.pnpm-store
dist
.next
.git
.vscode
.env
.env.local
*.log
coverage
Dockerfile*
docker-compose*
.github

BuildKit Optimizations

# syntax=docker/dockerfile:1.10

# Cache mount for package manager (reusable across builds)
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN --mount=type=cache,target=/root/.local/share/pnpm/store \
    corepack enable pnpm && pnpm install --frozen-lockfile

# Parallel build stages
FROM deps AS build-app
COPY src ./src
RUN pnpm build

FROM deps AS build-assets
COPY public ./public
RUN pnpm build:assets

# Merge in final stage
FROM node:22-alpine AS runner
COPY --from=build-app /app/dist ./dist
COPY --from=build-assets /app/public ./public

Cache backends (Buildx)

Pick by environment, not by habit:

Backend Use when Notes
type=registry Default for multi-runner CI / production Stores cache as a separate image; works anywhere a registry is reachable.
type=gha (v2) GitHub-hosted runners Buildx 0.21+ reads the v2 endpoint from env; requires BuildKit ≥ 0.20.
type=s3 / type=azblob Self-hosted CI on AWS/Azure Cheap blob storage, OIDC-auth supported.
type=local Single dev machine Not portable.

mode=max caches every intermediate layer (best hit-rate, larger storage); mode=min (default) caches only what is exported. For incremental builds the difference between a cache miss and mode=max hit is routinely 5 min → 30 s. [Source: Buildx cache backends]

docker buildx build \
  --cache-from type=registry,ref=ghcr.io/org/app:buildcache \
  --cache-to   type=registry,ref=ghcr.io/org/app:buildcache,mode=max \
  --sbom=true --provenance=mode=max \
  -t ghcr.io/org/app:$(git rev-parse --short HEAD) --push .

Docker Security Scanning

Reference scanners (2026):

Tool Strengths Caveats
Docker Scout First-party UX, policy gates, SBOM Tied to Docker ecosystem
Syft + Grype (Anchore) Modular: Syft generates SBOM once, Grype rescans on each CVE DB update. ~30-40% faster vulnerability-only scans Grype is vulnerability-only (no IaC/secret/license scanning)
Trivy All-in-one (CVE, misconfig, secret, license, IaC, K8s) The Trivy distribution channels were compromised in the 2026-03 TeamPCP campaign — verify the binary via cosign verify against the signed release and audit scan.aquasecurtiy.org (typosquat C2) before reintroducing

[Source: Trivy vs Grype 2026; SBOM generation tools compared]

# Docker Scout (CVE scan)
docker scout cves myimage:latest --only-severity critical,high

# Generate SBOM via Scout
docker scout sbom myimage:latest --format spdx-json > sbom.json

# Syft + Grype (modular alternative)
syft myimage:latest -o cyclonedx-json=sbom.cdx.json
grype sbom:sbom.cdx.json --fail-on high

# Cosign v3 keyless verify (Fulcio + Rekor v2)
cosign verify ghcr.io/org/app@sha256:<digest> \
  --certificate-identity-regexp "^https://github\.com/org/app/.+" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com
# CI integration — pin actions to commit SHA, not @v1
- uses: docker/scout-action@<sha>   # was @v1
  with:
    command: cves
    image: ${{ env.IMAGE }}
    only-severities: critical,high
    exit-code: true

Compose Watch (Dev Hot Reload)

Watch uses filesystem events (no polling) and — since Compose 5.x — delegates builds to Docker Bake for parallel/cached multi-platform rebuilds. [Source: Compose Develop Spec]

# compose.yaml
services:
  app:
    build: .
    develop:
      watch:
        - action: sync
          path: ./src
          target: /app/src
        - action: rebuild
          path: package.json
        - action: sync+restart
          path: ./config
          target: /app/config

Run with: docker compose watch


Compose Bridge (Compose → Kubernetes)

For teams migrating from Compose to Kubernetes, Compose Bridge (Docker Desktop 4.43+, July 2025) converts compose.yaml to Deployments, Services, ConfigMaps, Secrets, NetworkPolicies, and PVCs in one command. Since Docker Desktop 5.0 (March 2026) the new Compose for Kubernetes can deploy Compose files directly to a cluster without intermediate manifest generation. Useful for local prod-parity testing; for hand-tuned manifests still hand off to reference/kubernetes-config.md. [Source: Compose Bridge docs; InfoQ — Docker Desktop 4.43 Kubernetes Bridge]

# One-shot conversion
docker compose bridge convert -f compose.yaml -o ./k8s/

# Or use as kubectl plugin
kubectl compose-bridge convert -f compose.yaml | kubectl apply -f -

Container Runtime Hardening

Combine with the Dockerfile patterns above. Runtime flags belong in compose / orchestrator config, not the Dockerfile.

# compose.yaml — hardened runtime
services:
  app:
    image: ghcr.io/org/app@sha256:<digest>
    read_only: true
    tmpfs:
      - /tmp:size=64m
    cap_drop: [ALL]
    cap_add: [NET_BIND_SERVICE]   # only add back what you need
    security_opt:
      - no-new-privileges:true
      - seccomp=./seccomp-profile.json
    user: "1001:1001"
    pids_limit: 200
    ulimits:
      nofile: { soft: 1024, hard: 2048 }
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:3000/health"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 10s

Container Hardening — Full Rationale, Signing, and Compliance Timeline

Canonical detail behind the Core Contract bullet in SKILL.md.

  • Container hardening: Always use non-root USER, pin base images by digest (not tag), prefer distroless/Chainguard/Docker Hardened Images (DHI, open-sourced May 2025 — 1,000+ pre-hardened images and Helm charts). DHI reduces vulnerabilities by up to 95% vs. community images. Chainguard Images include SLSA Build Level 2 provenance attestations, Sigstore cryptographic signatures, and are rebuilt nightly from source with automated CVE patching. Drop all capabilities (--cap-drop=ALL) and add back only what's needed. Set --security-opt=no-new-privileges to prevent privilege escalation. Use read-only root filesystem (--read-only) where possible. Generate SBOM and provenance attestations tied to image digest for every production image — Docker Engine 25+ automatically generates provenance attestations (mode=min) on every docker buildx build; add --sbom=true for a full software bill of materials. Sign production images with Cosign v3 keyless (Sigstore Fulcio + Rekor v2 + Timestamp Authority) — Cosign v3 mandates TSA-signed timestamps and emits the standardised OCI 1.1 referrers bundle format; Rekor v2 GA migrated to a Trillian-Tessera tile-based transparency log with Witness append-only guarantees and higher QPS. Verify at deploy with cosign verify --certificate-identity=<identity> --certificate-oidc-issuer=<issuer>. Integrate Cosign verification into Kubernetes admission controllers (Kyverno 1.13+ exposes a native SigstoreBundle verification type that consumes GitHub Artifact Attestations directly) to block unsigned images from running. [Source: blog.sigstore.dev — Cosign v3, Rekor v2 GA; main.kyverno.io — 1.13 release]. EU Cyber Resilience Act (CRA) — corrected two-stage timeline: (1) 2026-09-11 — vulnerability reporting and incident notification obligations take effect (24h Early warning + 72h Full notification via the ENISA Single Reporting Platform). (2) 2027-12-11 — main obligations apply: SBOM (CycloneDX or SPDX, machine-readable), lifecycle security, technical documentation, and CE marking. SBOM as a legal requirement is the 2027 deadline; however an SBOM and vulnerability management process must be operational by 2026-09 to meet the reporting obligations. [Source: digital-strategy.ec.europa.eu — CRA Reporting; keysight.com — One-Year Countdown]. Adopt SLSA v1.2 as the current spec target (v1.0/v1.1 are superseded; v1.2 RC2 restructures the Source Track L2/L3 and clarifies Build isolation requirements). [Source: slsa.dev/spec/v1.2/whats-new]. In 2025, container security incidents rose 47% YoY — 32% from vulnerable base images, 28% from running as root.

Source: SKILL.md on GitHub

No alerts13d5 checks · Risk SAFE
  • Gen Agent Trust Hub13d

    The skill is a comprehensive DevOps and CI/CD maintenance tool that follows and promotes industry-standard security best practices. It includes detailed defenses against supply-chain attacks and enforces hardening techniques for containers and workflows.

  • Socket13d

    No alerts

  • Snyk13d

    Risk: LOW · No issues

  • Runlayer6mo

    3/8 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at e307415. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 2 weeks ago

README badge

README badge for simota/agent-skills/gear