Get the FREE Ultimate OpenClaw Setup Guide →
npx machina-cli add skill chaterm/terminal-skills/dockerfile --openclaw
Files (1)
SKILL.md
6.0 KB

Dockerfile 编写

概述

Dockerfile 最佳实践、安全扫描等技能。

指令详解

FROM

# 基础镜像
FROM ubuntu:22.04
FROM node:18-alpine
FROM python:3.11-slim

# 多阶段构建
FROM node:18 AS builder
FROM nginx:alpine AS production

# 使用 ARG 动态指定
ARG BASE_IMAGE=node:18-alpine
FROM ${BASE_IMAGE}

WORKDIR

# 设置工作目录(推荐使用绝对路径)
WORKDIR /app
WORKDIR /home/node/app

# 多次使用会切换目录
WORKDIR /app
WORKDIR src
# 当前目录: /app/src

COPY 与 ADD

# COPY(推荐)
COPY package.json ./
COPY src/ ./src/
COPY --chown=node:node . .

# 多文件复制
COPY package.json package-lock.json ./

# ADD(支持 URL 和解压)
ADD https://example.com/file.tar.gz /app/
ADD archive.tar.gz /app/           # 自动解压

# 推荐:优先使用 COPY,除非需要 ADD 的特殊功能

RUN

# Shell 形式
RUN apt-get update && apt-get install -y curl

# Exec 形式
RUN ["apt-get", "update"]

# 最佳实践:合并命令减少层数
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        curl \
        wget \
        git && \
    rm -rf /var/lib/apt/lists/*

CMD 与 ENTRYPOINT

# CMD - 默认命令(可被覆盖)
CMD ["node", "app.js"]
CMD ["npm", "start"]

# ENTRYPOINT - 入口点(不易被覆盖)
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["postgres"]

# 组合使用
ENTRYPOINT ["python"]
CMD ["app.py"]
# 运行: python app.py
# docker run myimage other.py -> python other.py

ENV 与 ARG

# ENV - 运行时环境变量
ENV NODE_ENV=production
ENV PORT=3000 HOST=0.0.0.0

# ARG - 构建时参数
ARG VERSION=1.0
ARG BUILD_DATE

# ARG 转 ENV
ARG APP_VERSION
ENV APP_VERSION=${APP_VERSION}

# 使用构建参数
# docker build --build-arg VERSION=2.0 .

EXPOSE

# 声明端口(文档作用)
EXPOSE 80
EXPOSE 443
EXPOSE 3000/tcp
EXPOSE 5000/udp

VOLUME

# 声明挂载点
VOLUME /data
VOLUME ["/data", "/logs"]

USER

# 切换用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

# 或使用 UID
USER 1000:1000

HEALTHCHECK

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/ || exit 1

# 禁用健康检查
HEALTHCHECK NONE

最佳实践模板

Node.js 应用

FROM node:18-alpine

# 创建非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app

# 先复制依赖文件
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production && npm cache clean --force

# 复制源代码
COPY --chown=appuser:appgroup . .

# 切换用户
USER appuser

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=3s \
    CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

CMD ["node", "app.js"]

Python 应用

FROM python:3.11-slim

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

WORKDIR /app

# 安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 创建非 root 用户
RUN useradd -m -r appuser && chown appuser:appuser /app
USER appuser

COPY --chown=appuser:appuser . .

EXPOSE 8000

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

Go 应用

# 构建阶段
FROM golang:1.21-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 main .

# 生产阶段
FROM scratch

COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/main /main

EXPOSE 8080

ENTRYPOINT ["/main"]

Java 应用

# 构建阶段
FROM maven:3.9-eclipse-temurin-17 AS builder

WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline

COPY src ./src
RUN mvn package -DskipTests

# 生产阶段
FROM eclipse-temurin:17-jre-alpine

RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "app.jar"]

.dockerignore

# Git
.git
.gitignore

# Node
node_modules
npm-debug.log

# Python
__pycache__
*.pyc
.venv
venv

# IDE
.idea
.vscode
*.swp

# Docker
Dockerfile*
docker-compose*
.dockerignore

# 文档
*.md
LICENSE

# 测试
test
tests
coverage

# 其他
.env
.env.*
*.log
tmp

安全检查

镜像扫描

# Docker Scout
docker scout cves myimage:tag
docker scout recommendations myimage:tag

# Trivy
trivy image myimage:tag

# Snyk
snyk container test myimage:tag

Dockerfile 检查

# Hadolint
docker run --rm -i hadolint/hadolint < Dockerfile

# Dockle
dockle myimage:tag

常见场景

场景 1:入口脚本

COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["app"]
#!/bin/bash
set -e

# 初始化逻辑
if [ "$1" = 'app' ]; then
    # 等待依赖服务
    until nc -z db 5432; do
        echo "Waiting for database..."
        sleep 1
    done
fi

exec "$@"

场景 2:多架构构建

# 创建 builder
docker buildx create --name mybuilder --use

# 多架构构建并推送
docker buildx build --platform linux/amd64,linux/arm64 \
    -t myrepo/myimage:tag --push .

场景 3:构建缓存

# 使用 BuildKit 缓存
docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t myimage:tag .

# 使用缓存
docker build --cache-from myimage:tag -t myimage:new .

故障排查

问题排查方法
构建慢优化 COPY 顺序、使用缓存
镜像大多阶段构建、精简基础镜像
权限问题检查 USER、文件权限
依赖问题检查网络、使用国内镜像源

Source

git clone https://github.com/chaterm/terminal-skills/blob/main/docker/dockerfile/SKILL.mdView on GitHub

Overview

本技能提供从 FROM 到 HEALTHCHECK 的完整 Dockerfile 指南,覆盖多阶段构建、工作目录、COPY/ADD、RUN 优化、ENV/ARG、EXPOSE、VOLUME、USER、HEALTHCHECK 以及运行时安全要点。你可以用它为 Node.js、Python、Go、Java 等应用快速生成高质量模板,并附带 .dockerignore 和安全检查流程。

How This Skill Works

当你提供目标应用栈与镜像目标时,技能会输出经过验证的 Dockerfile 模板,包含分阶段构建、最小化镜像、非 root 用户、健康检查和合理的默认命令。它还会标注潜在问题(如冗余 RUN 层、权限不足、ADD 的非必要功能等),并给出改进建议与替代方案,支持 .dockerignore 与安全检查步骤(镜像扫描、Hadolint、Dockle 等)。

When to Use It

  • 需要最小化镜像并优化构建缓存
  • 需要通过多阶段构建分离构建与运行时依赖
  • 需要使用非 root 用户提升安全性
  • 需要在镜像内设置健康检查、端口暴露和环境变量
  • 正在为 Node.js、Python、Go、Java 等应用生成生产镜像
  • 希望结合安全扫描工具进行持续集成的 Dockerfile 审查与改进

Quick Start

  1. 1) 提供你的应用栈和目标镜像(如 Node.js 18-alpine、Python 3.11-slim 等)以及是否需要多阶段构建。
  2. 2) 让技能生成一个完整的 Dockerfile(包含 FROM、WORKDIR、COPY/ADD、RUN、ENV/ARG、USER、EXPOSE、CMD/ENTRYPOINT、HEALTHCHECK)以及 .dockerignore。
  3. 3) 选择模板风格(如 Node.js、Python、Go、Java),获取对应的生产镜像最佳实践模板。
  4. 4) 将输出的 Dockerfile 和 .dockerignore 拷贝到工程中,使用 docker build 构建并结合安全检查工具进行审查。

Best Practices

  • 使用多阶段构建以分离构建工具和运行时依赖,尽量让最终镜像仅包含产物和运行时所需。
  • 优先使用 COPY 而非 ADD,除非你确实需要从 URL 获取文件或自动解压归档。
  • 尽量合并 RUN 指令,减少镜像层数,并在同一 RUN 中清理缓存(如 apt-get clean、rm -rf /var/lib/apt/lists/*)。
  • 固定镜像版本标签,避免使用 latest,以获得可重复的构建结果。
  • 创建非 root 用户并切换到该用户执行应用,提升容器运行时的安全性。
  • 为镜像指定 WORKDIR、明确的暴露端口和健康检查,便于运维监控与快速故障定位。
  • 在构建阶段使用 BuildKit 的缓存机制(如 --build-arg BUILDKIT_INLINE_CACHE=1),并可在后续构建中使用 --cache-from。
  • 将敏感信息通过 ARG/ENV 传入,避免在镜像中保存明文密钥。
  • 使用 .dockerignore 排除不需要的文件,减小构建上下文。
  • 对生产镜像进行安全扫描(镜像层漏洞、依赖分析),并在 CI 中集成 Hadolint、Dockle、Trivy 等工具。

Example Use Cases

  • Node.js 应用的最小化生产镜像示例:多阶段构建、非 root 用户、COPY --chown、RUN 的合并与清理、健康检查、CGO/依赖处理等。代码示例参照 Node.js 模板: FROM node:18-alpine RUN addgroup -S appgroup && adduser -S appuser -G appgroup WORKDIR /app COPY package*.json ./ RUN npm ci --only=production && npm cache clean --force COPY --chown=appuser:appgroup . . USER appuser EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=3s \ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1 CMD ["node","app.js"]
  • Python 应用生产镜像示例:Gunicorn+非 root、依赖分离、健康检查、端口暴露: FROM python:3.11-slim ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt RUN useradd -m -r appuser && chown -R appuser /app USER appuser COPY --chown=appuser:appuser . . EXPOSE 8000 CMD ["gunicorn","--bind","0.0.0.0:8000","app:app"]
  • Go 应用生产镜像示例:多阶段构建,静态编译、证书处理、最终镜像最小化: FROM golang:1.21-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 main . FROM scratch COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /app/main /main EXPOSE 8080 ENTRYPOINT ["/main"]
  • Java 应用生产镜像示例:Maven 构建阶段 + JRE 运行阶段,非 root 用户与最小化镜像: FROM maven:3.9-eclipse-temurin-17 AS builder WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests FROM eclipse-temurin:17-jre-alpine RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser WORKDIR /app COPY --from=builder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"]
  • 多架构构建示例(Buildx):支持 linux/amd64、linux/arm64 的镜像产出并推送: # 创建 builder docker buildx create --name mybuilder --use # 构建并推送多架构镜像 docker buildx build --platform linux/amd64,linux/arm64 \ -t myrepo/myimage:tag --push .
  • 场景示例:入口脚本与健康检查结合的生产镜像 COPY docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh ENTRYPOINT ["docker-entrypoint.sh"] CMD ["app"] #!/bin/bash set -e if [ "$1" = 'app' ]; then until nc -z db 5432; do echo "Waiting for database..." sleep 1 done fi exec "$@"

Frequently Asked Questions

Add this skill to your agents

Related Skills

Sponsor this space

Reach thousands of developers