Agent-almanac create-dockerfile
install
source · Clone the upstream repo
git clone https://github.com/pjt222/agent-almanac
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/zh-CN/skills/create-dockerfile" ~/.claude/skills/pjt222-agent-almanac-create-dockerfile-8779bc && rm -rf "$T"
manifest:
i18n/zh-CN/skills/create-dockerfile/SKILL.mdsource content
创建 Dockerfile
为通用应用项目编写生产就绪的 Dockerfile。
适用场景
- 容器化 Node.js、Python、Go、Rust 或 Java 应用程序
- 创建一致的构建/运行环境
- 为云部署或 Docker Compose 准备应用
- 项目中无现有 Dockerfile
输入
- 必需:项目语言和入口点(如
、npm start
)python app.py - 必需:依赖清单(package.json、requirements.txt、go.mod、Cargo.toml、pom.xml)
- 可选:目标环境(开发或生产)
- 可选:暴露端口
步骤
第 1 步:选择基础镜像
| 语言 | 开发镜像 | 生产镜像 | 大小 |
|---|---|---|---|
| Node.js | | | ~200MB |
| Python | | | ~150MB |
| Go | | | ~2MB |
| Rust | | | ~80MB |
| Java | | | ~200MB |
预期结果: 为生产镜像选择 slim/distroless 变体。
第 2 步:编写 Dockerfile(按语言)
Node.js
FROM node:22-bookworm-slim RUN groupadd -r appuser && useradd -r -g appuser -m appuser WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci --omit=dev COPY . . USER appuser EXPOSE 3000 CMD ["node", "src/index.js"]
Python
FROM python:3.12-slim-bookworm RUN groupadd -r appuser && useradd -r -g appuser -m appuser WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . USER appuser EXPOSE 8000 CMD ["python", "app.py"]
Go
FROM golang:1.23-bookworm AS builder WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 go build -o /app/server ./cmd/server FROM gcr.io/distroless/static COPY --from=builder /app/server /server EXPOSE 8080 ENTRYPOINT ["/server"]
Rust
FROM rust:1.82-bookworm AS builder WORKDIR /src COPY Cargo.toml Cargo.lock ./ RUN mkdir src && echo "fn main() {}" > src/main.rs && cargo build --release && rm -rf src COPY . . RUN touch src/main.rs && cargo build --release FROM debian:bookworm-slim RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* COPY --from=builder /src/target/release/myapp /usr/local/bin/myapp EXPOSE 8080 ENTRYPOINT ["myapp"]
Java (Maven)
FROM eclipse-temurin:21-jdk AS builder WORKDIR /src COPY pom.xml . RUN mvn dependency:go-offline -B COPY src ./src RUN mvn package -DskipTests FROM eclipse-temurin:21-jre COPY --from=builder /src/target/*.jar /app/app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "/app/app.jar"]
预期结果:
docker build -t myapp . 无错误完成。
失败处理: 检查基础镜像可用性和依赖安装命令。
第 3 步:ENTRYPOINT 与 CMD
| 指令 | 用途 | 覆盖方式 |
|---|---|---|
| 固定可执行文件 | 使用 覆盖 |
| 默认参数 | 使用尾部参数覆盖 |
| 两者结合 | + 通过 提供默认参数 | 参数仅覆盖 CMD |
对于具有单一用途的编译二进制文件使用
ENTRYPOINT。对于解释型语言使用 CMD,以便可以执行 docker run myapp bash。
第 4 步:创建 .dockerignore
.git .gitignore node_modules __pycache__ *.pyc target/ .env .env.* *.md !README.md .vscode .idea Dockerfile docker-compose*.yml
预期结果: 构建上下文排除开发产物。
第 5 步:添加非 root 用户
生产环境始终以非 root 身份运行:
RUN groupadd -r appuser && useradd -r -g appuser -m appuser USER appuser
对于 distroless 镜像,使用内置的 nonroot 用户:
FROM gcr.io/distroless/static:nonroot USER nonroot
第 6 步:构建和验证
docker build -t myapp:latest . docker run --rm myapp:latest docker image inspect myapp:latest --format '{{.Size}}'
预期结果: 容器启动,在预期端口响应,以非 root 身份运行。
失败处理: 使用
docker logs 检查日志。验证 WORKDIR、COPY 路径和暴露端口。
验证清单
-
无错误完成docker build - 容器启动且应用响应
-
排除不必要的文件.dockerignore - 应用以非 root 用户运行
- 依赖在源代码之前被复制(缓存效率)
- 镜像中未烘焙密钥或
文件.env
常见问题
- 在依赖安装前 COPY:每次代码更改都使依赖缓存失效。始终先复制清单文件。
- 以 root 运行:默认 Docker 用户是 root。生产环境始终添加非 root 用户。
- 缺少 .dockerignore:将
或node_modules
发送到构建上下文浪费时间和磁盘。.git - 使用
标签作为基础镜像:固定到特定版本(如latest
)以实现可重现性。node:22.11.0 - 忘记
:Python--no-cache-dir
默认缓存包,导致镜像膨胀。pip - ADD 与 COPY:使用
除非需要 URL 下载或 tar 解压(COPY
自动解压)。ADD
相关技能
- 使用 rocker 镜像的 R 特定 Dockerfilecreate-r-dockerfile
- 用于最小生产镜像的多阶段模式create-multistage-dockerfile
- 高级缓存策略optimize-docker-build-cache
- 与其他服务一起编排容器化应用setup-compose-stack