首页/云/Docker 容器速查/scratch 空镜像构建
镜像与构建107 条

scratch 空镜像构建

scratch 是保留字:从完全空的文件系统开始构建,只适合放静态链接的产物;CA 证书、时区等要自行复制。

Docker 容器速查云更新于 2026-10-13

scratch 是什么

scratch 是 Dockerfile 里的特殊保留字,表示从一个完全空的文件系统开始构建:镜像里没有 shell、没有 libc、没有包管理器,只有你显式 COPY 进去的文件。它只适合放静态编译产物(Go、Rust、C,且关闭 CGO),换来镜像可以小到几 MB、攻击面最小;代价是 CA 证书、时区、passwd 这些运行期数据要自己带进去。

基本信息

用途构建极致精简的静态二进制镜像
语法FROM scratch
适用范围Go / Rust / C 等静态编译产物
镜像内缺失shell、libc、包管理器、CA 证书、时区数据
运行限制只能用 exec 形式的 ENTRYPOINT / CMD

典型使用场景

  • Go 服务容器化:CGO_ENABLED=0 编译后直接放进空镜像
  • 安全敏感组件:无 shell 无包管理器,减少攻击者可用工具
  • 边缘与分发场景:镜像越小,拉取与分发成本越低
  • 极短启动的一次性任务与批处理程序
  • 作为体积基线,验证产物是否真的静态链接

多阶段构建示例

多阶段构建示例
# 构建阶段:静态编译
FROM golang:1.23 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -o /out/app ./cmd/app
# 运行阶段:空镜像只放必要文件
FROM scratch
COPY --from=build /out/app /app
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
USER 10001:10001
ENTRYPOINT ["/app"]

缺失项与补救

缺失项典型表现补救方式
CA 证书访问 HTTPS 报 x509: certificate signed by unknown authority从构建阶段 COPY ca-certificates.crt
时区数据日志时间错乱、本地时间计算错误COPY /usr/share/zoneinfo
shelldocker exec 进不去,HEALTHCHECK 无法执行不适合需要交互排障的负载
libc 与动态库启动立即报 not found 或 exec format error改为静态编译,或退回 alpine/debian 基础镜像
scratch 镜像无法 docker exec 进去排查,只能依赖宿主侧的 docker inspect、docker logs 以及应用自身输出到标准输出的日志。
HEALTHCHECK 的 CMD-SHELL 形式在 scratch 里必然失败,因为镜像中没有 shell;如需健康检查只能用可执行文件的 exec 形式。
部分运行时会读取系统的名称解析与用户数据库文件,空镜像里这些文件并不存在,遇到按用户名解析或特定 DNS 查询失败的情况,按实际报错把对应文件一并拷入再验证。

易错点

  • 忽略 CA 证书:应用访问 HTTPS 时报 x509 错误,看着像代码缺陷,实际是镜像里根本没有信任根证书
  • 忘记关闭 CGO 或引入动态链接库:构建日志一路正常,容器一启动就 not found,日志里也不会有更多线索
  • 把 scratch 用在需要排障的负载上:出事时既进不去容器,也跑不了诊断命令
  • 没有指定 USER:默认以 root 运行,白白浪费了空镜像带来的最小权限优势
  • 证书路径按宿主习惯硬编码:不同发行版路径不同,从构建阶段拷贝比手写路径更可靠

数据来源与参考

  • Docker 官方文档:Use the scratch image(docs.docker.com)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌