Loading...
Loading...
Expert guidance for Dockerfile authoring — the complete reference for writing production-grade Dockerfiles. Covers every instruction (FROM/RUN/COPY/ADD/ENV/ARG/WORKDIR/EXPOSE/CMD/ENTRYPOINT/USER/HEALTHCHECK/SHELL) with syntax, best practices, and common mistakes. Includes multi-stage build patterns (build+scratch, build+alpine, builder pattern), layer caching optimization strategies, .dockerignore rules, and language-specific production templates (Go/Rust/Java Spring Boot/Python FastAPI/Node.js Express/TypeScript). Use when the user asks about Dockerfile, how to write a Dockerfile, multi-stage build, layer optimization, or needs Dockerfile examples for a specific language. 使用场景:Dockerfile 编写、怎么写 Dockerfile、Dockerfile 指令、多阶段构建、multi-stage、层优化、layer cache、Dockerfile 模板.
npx skill4agent add full-stack-skills/docker-skills docker-dockerfileFROM <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 Practice | Why |
|---|---|
| Pin digest for production | Tags are mutable; digest is immutable |
| Use Alpine/slim variants | Smaller attack surface, smaller image |
| Static binaries need nothing else |
# ✅ 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/localCOPY [--chown=<user>:<group>] <src>... <dest>
COPY . /app
COPY ./binary /usr/local/bin/
COPY /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 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 /appWORKDIR /app
# All subsequent RUN/COPY/CMD use /app as base
# Prefer over:
RUN cd /app && npm install # ❌ cd doesn't persist# 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 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: 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"]# Create user and group
RUN addgroup --system app && adduser --system --ingroup app app
USER appHEALTHCHECK \
CMD wget -qO- http://localhost:8080/health || exit 1
# Dockerfile without shell (scratch):
HEALTHCHECK CMD /app/healthcheck || exit 1SHELL ["/bin/bash", "-euxo", "pipefail", "-c"]
RUN echo "Now using bash with strict mode"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 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY /app/server /server
USER 1000:1000
CMD ["/server"]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 /app/target/*.jar /app.jar
USER app
CMD ["java", "-jar", "/app.jar"]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 /app/dependencies/ ./
COPY /app/spring-boot-loader/ ./
COPY /app/snapshot-dependencies/ ./
COPY /app/application/ ./
USER app
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]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 /app/dist /app
COPY /app/node_modules /app/node_modules
USER app
CMD ["node", "/app/index.js"]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 /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"]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
.git
.gitignore
*.md
.env
.env.*
Dockerfile
docker-compose*.yml
node_modules
__pycache__
*.pyc
.git
.idea
.vscode
*.log
tmp/docker build -t app .docker runCOPY . .RUN installCOPY package.json . → RUN install → COPY src/ .USER <non-root>RUN addgroup -S app && adduser -S app -G appUSER appdocker exec myapp whoamiENV SECRET=value--mount=type=secretdocker run -e SECRET=$VAL.dockerignore.dockerignore.git node_modules .envdocker build --no-cache . 2>&1 | head -1RUN apt update && apt install&& rm -rf /var/lib/apt/lists/*--no-cacheubuntu:22.04alpine:3.20debian:bookworm-slimdocker images| 分类 | 场景 | 说明 |
|---|---|---|
| ✅ 能做 | 编写生产级 Dockerfile | 14 条指令完整参考 + 最佳实践 |
| ✅ 能做 | 多阶段构建(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 命令执行 | 使用 |
| ❌ 超范围 | 多平台构建(arm64/amd64) | 使用 |
| ❌ 超范围 | 容器编排(多容器) | 使用 |
| ❌ Skip | ✅ Use Instead |
|---|---|
Building images ( | |
| Multi-platform builds | |
| Compose file authoring | |
| Docker basics | |
| Running containers | |
--mount=type=secretUSER <non-root>COPY --chown📍 You are here:— Dockerfile 编写docker-dockerfile
basics → dockerfile → build → buildx → run → compose → ...docker-builddocker build