Get the FREE Ultimate OpenClaw Setup Guide →

docker

Scanned
npx machina-cli add skill DigitalPine/claude-skills/docker --openclaw
Files (1)
SKILL.md
8.5 KB

Docker Best Practices (2025)

First Question: Do You Need a Dockerfile?

For fast-moving projects, the fastest Docker setup has no Dockerfile at all.

Do you need a Dockerfile?
│
├─ Deploying to your own swarm/server?
│  └─ NO - Use mounted code pattern (see below)
│
├─ Publishing to Docker Hub / registry?
│  └─ YES - Others need to build your image
│
├─ CI/CD building images?
│  └─ YES - Need reproducible builds
│
├─ Complex native dependencies?
│  └─ MAYBE - If mount + base image isn't enough
│
├─ Open source project?
│  └─ YES - Contributors need to build/run
│
└─ Just deploying your own code?
   └─ NO - Mount it, move fast

Fast Path: Mounted Code Pattern

Build locally, mount into runtime container. No Dockerfile, no registry, instant deploys.

# docker-compose.yaml - the "no Dockerfile" approach
services:
  app:
    image: node:22-slim
    working_dir: /app
    volumes:
      - /absolute/path/to/project:/app:ro
    command: node dist/index.js
    environment:
      - NODE_ENV=production

Why this works:

  • pnpm build locally → mount dist/ into container
  • Code changes = rebuild + restart (no image rebuild)
  • Base images updated by just pulling latest
  • Perfect for internal services, hobby projects, fast iteration

When to graduate to Dockerfiles:

  • Image size matters (multi-stage shrinks significantly)
  • Need CI/CD to build images
  • Publishing for others to use
  • Native dependencies that need build-time compilation

When You DO Need a Dockerfile

Required Reading by Topic

⚠️ BEFORE providing Dockerfile guidance, read the relevant reference:

If user needs...Read FIRST
Multi-stage buildsreferences/multi-stage-patterns.md
BuildKit features (cache mounts, secrets)references/buildkit-features.md
Base image selectionreferences/base-images.md
Language-specific patternsreferences/language-patterns.md
Security hardeningreferences/security-hardening.md

Skipping references leads to outdated patterns. Docker best practices change frequently.

5-Minute Essentials (Always Do These)

These take 5 minutes and prevent 80% of problems:

1. Pin your base image (30 sec)

# BAD
FROM node:latest

# GOOD
FROM node:22-slim

2. Add .dockerignore (2 min)

.git
node_modules
dist
.env*
*.log

Copy template: assets/dockerignore.template

3. Non-root user (2 min)

# Add before final CMD
RUN groupadd -r app && useradd -r -g app app
USER app

4. Order layers correctly (30 sec)

# Dependencies first (cached)
COPY package*.json ./
RUN npm ci

# Code last (changes often)
COPY . .

That's it for fast-moving projects. Everything below is for when you need to optimize further.


Comprehensive Optimization (When Publishing/Scaling)

Multi-Stage Builds

Separate build-time from runtime for smaller images:

# syntax=docker/dockerfile:1

FROM node:22 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-slim AS production
WORKDIR /app
RUN groupadd -r app && useradd -r -g app app
COPY --from=builder --chown=app:app /app/dist ./dist
COPY --from=builder --chown=app:app /app/node_modules ./node_modules
USER app
CMD ["node", "dist/index.js"]

→ See: references/multi-stage-patterns.md for advanced patterns

BuildKit Cache Mounts

Speed up dependency installation:

# syntax=docker/dockerfile:1
RUN --mount=type=cache,target=/root/.npm npm ci

→ See: references/buildkit-features.md for cache mounts, secrets, COPY --link

Base Image Selection

NeedImageSize
Node.jsnode:22-slim~200MB
Pythonpython:3.12-slim~150MB
Goscratch or gcr.io/distroless/static~2MB
Maximum securitygcr.io/distroless/*2-20MB

Apple Silicon Limitation: Multi-stage Go builds with docker buildx --platform linux/amd64 segfault on Apple Silicon Macs due to QEMU issues with Go 1.24+. Use native cross-compilation instead:

GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o app .
# Then use simple Dockerfile that just copies the binary

See assets/go-prebuilt.dockerfile for the pattern.

→ See: references/base-images.md for detailed selection guide

Language-Specific Templates

StackTemplateKey Feature
Node.js/pnpmassets/nodejs-pnpm.dockerfileCache mounts, corepack
Go (multi-stage)assets/go-static.dockerfileScratch/distroless, static binary
Go (pre-built)assets/go-prebuilt.dockerfileApple Silicon compatible, native cross-compile
Python/uvassets/python-uv.dockerfileModern uv package manager
Next.jsassets/nextjs-standalone.dockerfileStandalone output mode

→ See: references/language-patterns.md for detailed patterns


Dockerfile Audit Checklist

When reviewing any Dockerfile:

Must Fix (Security)

  • Non-root USER instruction
  • No secrets in ENV or COPY
  • Pinned base image versions (no :latest)
  • .dockerignore excludes .env, .git, secrets

Should Fix (Size/Speed)

  • Multi-stage separates build from runtime
  • Layer order: deps first, code last
  • Uses *-slim or smaller base

Nice to Have

  • BuildKit cache mounts
  • COPY --link for multi-stage
  • HEALTHCHECK defined
  • OCI labels for metadata

Quick Reference

Common Anti-Patterns

# BAD: Everything wrong
FROM node:latest
COPY . .
RUN npm install
ENV DATABASE_URL=postgres://secret
CMD ["npm", "start"]

# GOOD: Fixed
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN groupadd -r app && useradd -r -g app app
USER app
CMD ["node", "dist/index.js"]

Size Targets

TypeTargetExcellent
Go binary< 20MB< 10MB
Node.js API< 200MB< 100MB
Python API< 200MB< 100MB

Build Time Targets

ChangeTarget
Code only< 30s
Dependencies< 2min

Integration with Swarm

If using Docker Swarm with Traefik:

Mounted code (no Dockerfile):

services:
  app:
    image: node:22-slim
    volumes:
      - /absolute/path:/app:ro
    deploy:
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.myapp.rule=Host(`myapp.example.com`)"

Built image (with Dockerfile):

services:
  app:
    image: myregistry/myapp:1.0.0
    deploy:
      labels:
        - "traefik.enable=true"
        # ...

Decision Trees

Creating New Project

Need Docker?
├─ Internal service, fast iteration → Mounted code, no Dockerfile
├─ Publishing to registry → Full Dockerfile (use templates)
├─ Open source → Full Dockerfile + clear build instructions
└─ Unsure → Start with mounted code, add Dockerfile later

Auditing Existing Dockerfile

Priority order:
1. Security (non-root, no secrets) → Fix immediately
2. Base image (slim, pinned) → Quick win
3. .dockerignore → 5 minutes, big impact
4. Multi-stage → If image > 500MB
5. Cache mounts → If builds > 2min

Navigation

TopicReference
Base image selectionreferences/base-images.md
Multi-stage patternsreferences/multi-stage-patterns.md
Security hardeningreferences/security-hardening.md
BuildKit featuresreferences/buildkit-features.md
Language patternsreferences/language-patterns.md
TemplateUse Case
assets/nodejs-pnpm.dockerfileNode.js with pnpm
assets/go-static.dockerfileGo to scratch
assets/python-uv.dockerfilePython with uv
assets/nextjs-standalone.dockerfileNext.js standalone
assets/dockerignore.templateStandard .dockerignore

Version Info

  • Last updated: December 2025
  • Docker version: 27.x+ (BuildKit default)
  • Philosophy: Start simple, optimize when needed
  • Sources: Docker docs, OWASP, Google Distroless

Source

git clone https://github.com/DigitalPine/claude-skills/blob/main/plugins/docker/skills/docker/SKILL.mdView on GitHub

Overview

This skill provides Docker guidance tailored for fast-moving teams. It starts by asking 'Do you need a Dockerfile?' and often recommends the mounted code pattern for speed. When a Dockerfile is needed, it covers 2025 best practices for multi-stage builds, security hardening, BuildKit optimization, and language-specific patterns, useful for setting up Docker, auditing Dockerfiles, or optimizing builds/images.

How This Skill Works

Guidance begins with a fast path that avoids Dockerfiles by mounting code into the runtime container. When a Dockerfile is required, it points you to references on multi-stage builds, BuildKit, base images, and language-specific patterns, then offers a 5-minute essentials checklist and, for publishing and scaling, comprehensive optimization steps.

When to Use It

  • Setting up Docker for a project with no Dockerfile (mounted code pattern)
  • Auditing existing Dockerfiles for security and efficiency
  • Optimizing builds and images via multi-stage builds and BuildKit
  • Preparing images for CI/CD pipelines or private registries
  • Open source projects where contributors need to build/run quickly

Quick Start

  1. Step 1: Decide if you can use a mounted code pattern or need a Dockerfile
  2. Step 2: If using a Dockerfile, implement the 5-minute essentials (pin base image, .dockerignore, non-root user, correct layer order)
  3. Step 3: For optimization, adopt multi-stage builds and BuildKit cache mounts and consult references for advanced patterns

Best Practices

  • Pin your base image to a specific tag (avoid latest)
  • Add a .dockerignore to minimize build context
  • Run the container as a non-root user
  • Order layers to maximize caching (dependencies first, code last)
  • Use multi-stage builds and BuildKit features for security and smaller images

Example Use Cases

  • Shifting from a Dockerfile-heavy workflow to a mounted code pattern for internal microservices
  • Node.js service migrated to multi-stage builds and slim base images to reduce image size
  • CI/CD pipeline builds and publishes images to a private registry using BuildKit
  • Open-source project enabling contributors to run code with mounted volumes to speed onboarding
  • Security hardening audit applied to existing Dockerfiles with non-root users and restricted perms

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers