优先使用官方-slim镜像(如python:3.12-slim)而非alpine,避免musl/glibc兼容问题;run命令合并安装与清理以减小体积;统一用copy代替add防意外解压或url缓存失效;多阶段构建分离编译与运行环境;务必配置.dockerignore过滤无关文件。

用 FROM 选基础镜像时,别只看名字大小
很多人一上来就搜“最小 Docker 镜像”,然后选 alpine,结果跑 glibc 程序直接报 not found 或 No such file or directory——其实是动态链接错了。Alpine 用的是 musl,不是 glibc,Python/Go 编译的二进制如果没静态链接,就挂。
实操建议:
- 优先用官方语言镜像的
-slim版本,比如python:3.12-slim(基于 Debian,兼容性好,体积也不大) - 确认你打包的二进制是否依赖
glibc:在宿主机上跑ldd your-binary | grep libc,有libc.so.6就别硬上 Alpine - 真要 Alpine,用
apk add --no-cache装依赖,别留/var/cache/apk
RUN 合并命令不是为了少写几行,是为了减少层和缓存失效
Docker 每个 RUN 都建一层,中间产物不自动清理。比如先 apt update && apt install,再 rm -rf /var/lib/apt/lists/*,这两步分开写,第二层里确实删了,但第一层还留着整个 apt 缓存目录,镜像体积照样大。
实操建议:
- 把安装 + 清理写在同一行
RUN apt update && apt install -y curl && rm -rf /var/lib/apt/lists/* - 避免
RUN pip install单独成行——它会把整个pip缓存打进镜像。改用RUN pip install --no-cache-dir - 如果要用
curl下东西,别装完就走,加&& rm /usr/bin/curl(前提是后续不需要)
COPY 和 ADD 别混用,ADD 的自动解压和远程拉取是坑源
ADD 看起来方便:支持 tar 自动解压、支持 URL 下载。但正因如此,它容易触发意外行为。比如 ADD app.tar.gz /app/,你以为只是复制,其实它默默解压了;更糟的是,如果 app.tar.gz 里有绝对路径(如 /etc/passwd),Docker 会照写进去,可能覆盖关键文件。
本书全面介绍PHP脚本语言和MySOL数据库这两种目前最流行的开源软件,主要包括PHP和MySQL基本概念、PHP扩展与应用库、日期和时间功能、PHP数据对象扩展、PHP的mysqli扩展、MySQL 5的存储例程、解发器和视图等。本书帮助读者学习PHP编程语言和MySQL数据库服务器的最佳实践,了解如何创建数据库驱动的动态Web应用程序。
实操建议:
- 一律用
COPY,需要解压就显式写RUN tar -xzf - 绝不用
ADD拉远程 URL:ADD https://.../script.sh /tmp/会让构建缓存完全失效(URL 内容变,层就重做),改用RUN curl -fsSLO+COPY分离关注点 -
COPY --chown比RUN chown更干净,尤其对非 root 用户启动的服务
多阶段构建不是炫技,是解决“编译环境 vs 运行环境”错位
很多 Go/Node/Rust 项目在镜像里既装了 go 又放了 go build 出来的二进制,结果镜像里塞了一堆 /usr/local/go、pkg、mod 目录——运行根本不需要。这类镜像不仅大,还暴露编译工具链,增加攻击面。
实操建议:
- 编译阶段用
golang:1.22,运行阶段用debian:bookworm-slim或scratch(Go 静态编译后可上scratch) - 用
COPY --from=builder显式挑出二进制,别COPY .整个目录 - 注意:多阶段不能跨 stage 共享环境变量或 shell 设置,
ARG要在每个 stage 里重新声明
最常被忽略的一点:.dockerignore 文件没配好,node_modules、__pycache__、.git 全塞进镜像,体积虚高、构建变慢、还可能泄露敏感信息。它比任何 RUN rm 都管用——从源头过滤。









