mcpField
D
docker-dockerfile

docker-dockerfile

github.com/full-stack-skills云与 DevOps3125 次安装4 周前更新
代码仓库

关于 docker-dockerfile

面向需要构建应用容器镜像的开发者,提供编写和优化 Dockerfile 的参考。内容涵盖指令用法、按语言区分的多阶段构建模式、层缓存和生产环境加固;不负责执行镜像构建或编排。

主要功能

  1. 01常见 Dockerfile 指令及用法参考
  2. 02适用于 Go、Java、Node.js 和 Python 的多阶段构建模式
  3. 03层缓存与依赖优先复制的指导
  4. 04镜像精简、安全和生产加固实践
  5. 05常见 Dockerfile 问题的排查建议

适用场景

  1. 01为应用运行环境编写 Dockerfile
  2. 02优化依赖层和构建缓存
  3. 03检查 Dockerfile 的安全性与生产就绪情况

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/full-stack-skills/docker-skills --skill docker-dockerfile

安装后在 Claude Code 中输入/docker-dockerfile确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evaluation-report.html
agents/
openai.yaml
examples/
01-multi-stage-go.md
02-multi-stage-java.md
03-spring-boot-layers.md
04-multi-stage-node.md
05-multi-stage-python.md
references/
01-dockerfile-instructions.md
02-layer-caching.md
03-dockerignore.md
04-image-size-optimization.md
05-multi-stage-patterns.md

详细介绍

Dockerfile——完整编写指南

用于编写生产级 Dockerfile 的专家参考。涵盖每条指令、每种模式和每项优化。

适用场景

用户提及以下内容时,始终使用此技能:

  • “Dockerfile”“怎么写 Dockerfile”“Dockerfile 指令”
  • “多阶段构建”“multi-stage build”
  • “Dockerfile 层优化”“layer caching”
  • “Dockerfile 模板”,语言专属模板:“Go Dockerfile”“Java Dockerfile”“Python Dockerfile”
  • 需要创建或优化 Dockerfile
  • “Dockerfile 最佳实践”

指令参考

FROM——基础镜像
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)
最佳实践原因
生产环境固定摘要标签可变;摘要不可变
使用 Alpine/slim 变体减小攻击面和镜像体积
Go/Rust 使用 FROM scratch静态二进制文件不需要其他内容
RUN——执行命令
# ✅ 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 [--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——复制并自动解压
# 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——设置工作目录
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——声明端口
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 与 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——切换到非 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——更改默认 Shell
SHELL ["/bin/bash", "-euxo", "pipefail", "-c"]
RUN echo "Now using bash with strict mode"

多阶段构建模式

模式 1:构建二进制文件 + 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"]
模式 2:构建 + 最小化运行时(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"]
模式 3:优化层结构(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"]
模式 4:构建 + Alpine(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"]
模式 5:Python 依赖 + Slim 运行时
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"]

层缓存策略

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/

工作流——推荐编写流程

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

注意事项——常见陷阱

  • 在 RUN install 前执行 COPY . .:每次代码变更都会使依赖层缓存失效,导致从头开始重新构建。→ 解决方法:始终先复制依赖:COPY package.json . → RUN install → COPY src/ .。
  • 默认使用 root 用户:始终在 Dockerfile 末尾使用 USER <non-root>。以 root 身份逃逸容器等同于获得主机 root 权限。→ 解决方法:添加 RUN addgroup -S app && adduser -S app -G app + USER app;使用 docker exec myapp whoami 验证。
  • 在 Dockerfile 中使用 ENV SECRET=value:该值会永久写入镜像层。→ 解决方法:使用 BuildKit --mount=type=secret,或在运行时注入 docker run -e SECRET=$VAL。
  • 没有 .dockerignore:整个项目都会发送到构建上下文中,导致构建缓慢并泄露敏感文件。→ 解决方法:创建 .dockerignore,至少包含 .git node_modules .env;使用 docker build --no-cache . 2>&1 | head -1 验证。
  • 执行 RUN apt update && apt install 后不清理:软件包列表会留在镜像层中。→ 解决方法:在命令末尾添加 && rm -rf /var/lib/apt/lists/*;对于 apk,使用 --no-cache 标志。
  • 基础镜像过大:ubuntu:22.04(77 MB)与 alpine:3.20(7 MB)相比体积更大。→ 解决方法:优先使用 Alpine;如果需要 glibc,则使用 debian:bookworm-slim;使用 docker images 检查体积。

边界——适用与不适用场景

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

不应使用此技能的场景

❌ 跳过✅ 改用
构建镜像(docker build ...)docker-build
多平台构建docker-buildx
编写 Compose 文件docker-compose
Docker 基础知识docker-basics
运行容器docker-run

安全性与稳定性

  • 所有 Dockerfile 模板仅供学习参考。用于生产环境前,请先审查并加固。
  • 切勿在 Dockerfile 中嵌入机密信息。请使用 BuildKit --mount=type=secret 或在运行时注入。
  • 生产环境中始终使用 USER <non-root>。为该用户复制文件时,请使用 COPY --chown。
  • 为确保生产环境的可复现性,请固定基础镜像摘要。

📚 官方文档参考

文档地址
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 技能之旅

📍 你当前所在位置:docker-dockerfile — Dockerfile 编写

basics → dockerfile → build → buildx → run → compose → ...

→ 下一步:docker-build — 使用 docker build 构建镜像

评论

支持 Markdown