Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
full-statck-skills avatar

Docker Dockerfile

  • 11 installs
  • 2 repo stars
  • Updated July 29, 2026
  • full-statck-skills/docker-skills

Write production Dockerfiles with correct instructions, multi-stage builds, and layer caching, using language-specific templates for Go, Python, Node, and Java.

About

A complete reference for authoring production-grade Dockerfiles, covering every instruction plus multi-stage builds and layer optimization. A developer uses it when writing or improving a Dockerfile.

  • Every Dockerfile instruction with syntax, best practices, and common mistakes
  • Multi-stage builds, layer caching, .dockerignore, and language-specific templates

Docker Dockerfile by the numbers

  • 11 all-time installs (skills.sh)
  • Ranked #993 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
  • Data as of Jul 30, 2026 (Skillselion catalog sync)
npx skills add https://github.com/full-statck-skills/docker-skills --skill docker-dockerfile

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs11
repo stars2
Last updatedJuly 29, 2026
Repositoryfull-statck-skills/docker-skills

What it does

Write production Dockerfiles with correct instructions, multi-stage builds, and layer caching, using language-specific templates for Go, Python, Node, and Java.

Files

SKILL.mdMarkdownGitHub ↗

Dockerfile — 完整编写指南

Expert reference for writing production-grade Dockerfiles. Every instruction, every pattern, every optimization.

When to Use

ALWAYS use this skill when the user mentions:

  • "Dockerfile", "怎么写 Dockerfile", "Dockerfile 指令"
  • "多阶段构建", "multi-stage build"
  • "Dockerfile 层优化", "layer caching"
  • "Dockerfile 模板", language-specific: "Go Dockerfile", "Java Dockerfile", "Python Dockerfile"
  • Need to create or optimize a Dockerfile
  • "Dockerfile best practices"

Instruction Reference

FROM — Base Image

FROM <image>[:<tag>] [AS <stage-name>]
FROM alpine:3.20                           # Tag
FROM alpine:3.20@sha256:abc123...def456     # Digest (production!)
FROM golang:1.22-alpine AS builder          # Named stage
FROM scratch                                 # Empty image (for static binaries)
Best PracticeWhy
Pin digest for productionTags are mutable; digest is immutable
Use Alpine/slim variantsSmaller attack surface, smaller image
FROM scratch for Go/RustStatic binaries need nothing else

RUN — Execute Commands

# ✅ Chain commands, clean in same layer
RUN apk add --no-cache curl && \
    curl -fsSL https://example.com/script.sh -o /usr/local/bin/script && \
    chmod +x /usr/local/bin/script

# ❌ Each RUN = new layer (bloat)
RUN apk add curl
RUN curl ... -o /usr/local/bin/script
RUN chmod +x /usr/local/bin/script

# Multi-line readability
RUN set -eux; \
    apk add --no-cache \
      curl \
      ca-certificates \
      tzdata; \
    curl -fsSL ... | tar xz -C /usr/local

COPY — Copy Files

COPY [--chown=<user>:<group>] <src>... <dest>
COPY . /app
COPY --chown=app:app ./binary /usr/local/bin/
COPY --from=builder /app/build /app       # From another stage (multi-stage)
# ✅ Layer-friendly: copy deps first, then source
COPY go.mod go.sum ./
RUN go mod download
COPY . .

# ❌ Source change invalidates dependency cache
COPY . .
RUN go mod download

ADD — Copy + Auto-extract

# ADD auto-extracts tar archives
ADD archive.tar.gz /app/

# Prefer COPY unless you need tar extraction
COPY archive.tar.gz /app/
RUN tar xzf /app/archive.tar.gz -C /app

WORKDIR — Set Working Directory

WORKDIR /app
# All subsequent RUN/COPY/CMD use /app as base

# Prefer over:
RUN cd /app && npm install   # ❌ cd doesn't persist

ENV & ARG

# ARG: build-time only (not in final image)
ARG VERSION=1.0.0
FROM myapp:${VERSION}

# ENV: runtime (persists in image)
ENV NODE_ENV=production \
    PORT=8080

# Combine: pass ARG to ENV
ARG APP_VERSION
ENV APP_VERSION=${APP_VERSION}

EXPOSE — Document Ports

EXPOSE 8080
EXPOSE 8080/tcp     # Protocol-specific
EXPOSE 8080/udp

# Note: EXPOSE does NOT publish ports. Use -p at runtime:
# docker run -p 8080:8080 myapp

CMD vs ENTRYPOINT

# CMD: default command (overridable)
CMD ["nginx", "-g", "daemon off;"]
# docker run myimage echo hello → overrides CMD

# ENTRYPOINT: fixed entry (not overridable)
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
# docker run myimage → runs: docker-entrypoint.sh nginx -g 'daemon off;'
# docker run myimage echo hello → runs: docker-entrypoint.sh echo hello

# Common pattern: script + default args
ENTRYPOINT ["/entrypoint.sh"]
CMD ["start"]

USER — Switch to Non-Root

# Create user and group
RUN addgroup --system app && adduser --system --ingroup app app
USER app

HEALTHCHECK

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD wget -qO- http://localhost:8080/health || exit 1

# Dockerfile without shell (scratch):
HEALTHCHECK --interval=30s CMD /app/healthcheck || exit 1

SHELL — Change Default Shell

SHELL ["/bin/bash", "-euxo", "pipefail", "-c"]
RUN echo "Now using bash with strict mode"

Multi-Stage Build Patterns

Pattern 1: Build Binary + Scratch (Go/Rust)

FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o server .

FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/server /server
USER 1000:1000
CMD ["/server"]

Pattern 2: Build + Minimal Runtime (Java)

FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests

FROM eclipse-temurin:21-jre-alpine
RUN addgroup --system app && adduser -S -G app app
COPY --from=builder /app/target/*.jar /app.jar
USER app
CMD ["java", "-jar", "/app.jar"]

Pattern 3: Layer-Optimized (Spring Boot)

FROM eclipse-temurin:21-jre-alpine AS builder
WORKDIR /app
COPY build/libs/*.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract

FROM eclipse-temurin:21-jre-alpine
RUN addgroup --system app && adduser -S -G app app
# Layers in dependency order (max cache)
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./
USER app
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]

Pattern 4: Build + Alpline (Node.js)

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

FROM node:22-alpine
RUN addgroup --system app && adduser -S -G app app
COPY --from=builder /app/dist /app
COPY --from=builder /app/node_modules /app/node_modules
USER app
CMD ["node", "/app/index.js"]

Pattern 5: Python Dependencies + Slim Runtime

FROM python:3.12 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt

FROM python:3.12-slim
RUN groupadd --system app && useradd --system -g app app
COPY --from=builder /root/.local /home/app/.local
COPY . /app
ENV PATH=/home/app/.local/bin:$PATH
USER app
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]

Layer Caching Strategy

Docker builds layers from top to bottom.
A changed layer invalidates ALL layers below it.

✅ CORRECT order:
  FROM base                  ← rarely changes
  RUN install-system-deps    ← changes with system updates
  COPY go.mod go.sum ./      ← changes with dependency changes
  RUN go mod download        ← changes with dependency changes
  COPY . .                   ← changes every commit ← MUST BE LAST

❌ WRONG order (slow builds):
  COPY . .                   ← changes every commit
  RUN go mod download        ← reruns every time!

.dockerignore

# .dockerignore
.git
.gitignore
*.md
.env
.env.*
Dockerfile
docker-compose*.yml
node_modules
__pycache__
*.pyc
.git
.idea
.vscode
*.log
tmp/

Workflow — 推荐编写流程

Step 1: 确定语言和运行时: Go/Java/Node.js/Python → 选择基础镜像 Step 2: 选择构建模式: 单阶段/多阶段/Spring Boot 分层 → 从 templates 选模板 Step 3: 编写 Dockerfile: 先 COPY 依赖 → RUN install → COPY 源码 → CMD Step 4: 验证: docker build -t app . + docker run + dive 分析镜像大小 Step 5: 生产加固: USER 非 root、HEALTHCHECK、固定 digest、Security 检查

Gotchas — Common Pitfalls

  • `COPY . .` before `RUN install`: Every code change invalidates the dependency layer — rebuilds from scratch. → Recovery: Always copy deps first: COPY package.json . → RUN install → COPY src/ ..
  • Root user by default: Always USER <non-root> at the end of Dockerfile. Escaping the container as root = host root. → Recovery: Add RUN addgroup -S app && adduser -S app -G app + USER app; verify with docker exec myapp whoami.
  • `ENV SECRET=value` in Dockerfile: Baked into image layers forever. → Recovery: Use BuildKit --mount=type=secret or runtime injection docker run -e SECRET=$VAL.
  • No `.dockerignore`: Sends entire project to build context — slow and leaks sensitive files. → Recovery: Create .dockerignore with at minimum .git node_modules .env; verify with docker build --no-cache . 2>&1 | head -1.
  • `RUN apt update && apt install` without cleanup: Leaves package lists in layer. → Recovery: Chain with && rm -rf /var/lib/apt/lists/*; for apk: --no-cache flag.
  • Heavy base image: ubuntu:22.04 (77 MB) vs alpine:3.20 (7 MB). → Recovery: Prefer alpine; if glibc needed, use debian:bookworm-slim; check size with docker images.

Boundary — 能力边界(适用与不适用场景)

分类场景说明
✅ 能做编写生产级 Dockerfile14 条指令完整参考 + 最佳实践
✅ 能做多阶段构建(Go/Java/Node/Python)5 种语言专属模板
✅ 能做层缓存优化COPY 依赖优先 + RUN 合并 + BuildKit cache mount
✅ 能做镜像瘦身5 步法路线图:多阶段→Alpine→distroless→清理→dive
⚠️ 需条件私有依赖安装需配合 BuildKit --secret 或 SSH forwarding
⚠️ 需条件CMD vs ENTRYPOINT 选择见指令参考中的决策树(工具用 ENTRYPOINT,服务用 CMD)
❌ 超范围docker build 命令执行使用 docker-build
❌ 超范围多平台构建(arm64/amd64)使用 docker-buildx
❌ 超范围容器编排(多容器)使用 docker-compose

When NOT to Use This Skill

❌ Skip✅ Use Instead
Building images (docker build ...)docker-build
Multi-platform buildsdocker-buildx
Compose file authoringdocker-compose
Docker basicsdocker-basics
Running containersdocker-run

Security & Stability

  • All Dockerfile templates are educational. Review and harden before production use.
  • Never embed secrets in Dockerfile. Use BuildKit --mount=type=secret or runtime injection.
  • Always USER <non-root> for production. Use COPY --chown when copying files for that user.
  • Pin base image digests for production reproducibility.

📚 官方文档参考

文档地址
Dockerfile 参考https://docs.docker.com/reference/dockerfile/
Docker Build 概述https://docs.docker.com/build/
构建最佳实践https://docs.docker.com/build/building/best-practices/
多阶段构建https://docs.docker.com/build/building/multi-stage/
.dockerignorehttps://docs.docker.com/build/building/context/#dockerignore-files
镜像层与缓存https://docs.docker.com/build/cache/

🧭 Docker Skills Journey

📍 You are here: `docker-dockerfile` — Dockerfile 编写
basics → dockerfile → build → buildx → run → compose → ...

→ Next: docker-build — Build images with docker build

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.