关键不是删文件,而是从构建逻辑上切断冗余产生路径:合并run指令实现安装与清理同层完成,用多阶段构建隔离构建环境与运行环境,选用小体积基础镜像(如alpine或distroless),并配合.dockerignore过滤无用上下文。
关键不是“删文件”,而是让每层只保留它该有的东西——从构建逻辑上切断冗余的产生路径。
合并 RUN 指令,清理动作必须在同层完成
每一行 RUN 都生成一个新层,如果安装软件后在下一层才删缓存,那安装包本身仍躺在前一层里,永远删不掉。
- ❌ 错误写法(三层,残留完整 apt 缓存):
RUN apt-get updateRUN apt-get install -y curlRUN rm -rf /var/lib/apt/lists/* - ✅ 正确写法(单层,安装+清理一气呵成):
RUN apt-get update && apt-get install -y --no-install-recommends curl && rm -rf /var/lib/apt/lists/*
用多阶段构建,彻底隔离构建环境与运行环境
编译工具、源码、测试依赖这些根本不该进最终镜像。多阶段构建让它们只活在 builder 阶段,不留下任何痕迹。
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
- 第一阶段用 golang:1.21 安装 SDK、编译二进制
- 第二阶段直接 FROM alpine:3.18,只 COPY 第一阶段产出的可执行文件
- 最终镜像里没有 Go、没有 .go 源码、没有 mod 缓存,只有运行所需的二进制和 ca-certificates
选对基础镜像,从源头控制层体积
基础层越小,后续所有层的“放大基数”就越小。ubuntu:22.04 基础层约 70MB,alpine:3.18 约 5MB,distroless 更是只含 runtime 和证书。
- 开发调试阶段可用 ubuntu 或 debian,但生产镜像务必切换到 alpine 或 distroless
- 注意:alpine 使用 musl libc,某些 C 扩展可能不兼容;distroless 连 sh 都没有,适合静态二进制部署
配合 .dockerignore,不让垃圾进入构建上下文
构建时传给 Docker daemon 的上下文(context)如果包含 node_modules、.git、log 文件等,即使 Dockerfile 没 COPY,也会拖慢构建速度,还可能被意外引用。
- 在项目根目录放 .dockerignore,内容示例:
node_modules/.git*.log.env.*dist/ - 执行
docker build .前,Docker 会先打包这个过滤后的上下文,大小直接影响构建启动时间和网络开销










