run 指令在构建阶段执行并生成新镜像层,支持 shell(如 run apt-get update && apt-get install -y curl)和 exec(如 run ["apt-get", "install", "-y", "curl"])两种格式,推荐合并操作、及时清理以减少层数,避免泄露敏感信息。

RUN 指令是 Docker 构建过程中安装依赖的核心手段,它不是在运行中的容器里临时执行命令,而是在构建镜像时逐层执行并固化结果。用对 RUN,才能让镜像轻、快、安全。
明确 RUN 的作用时机和效果
RUN 只在 构建阶段 执行,每条 RUN 都会生成一个新的镜像层,把命令的执行结果(比如装上的软件、写入的文件)永久保存进去。这意味着:容器启动后,这些软件就已存在,无需再装;但反过来说,如果 RUN 写得松散,就会产生大量冗余层,拖慢构建、增大镜像体积。
两种写法:shell 模式与 exec 模式
推荐优先使用 shell 模式(简洁常用),必要时切换 exec 模式(更可控):
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
-
Shell 模式:RUN apt-get update && apt-get install -y curl
自动调用 /bin/sh -c,支持管道、变量展开(如 $HOME)、逻辑连接符(&&、||) -
Exec 模式:RUN ["apt-get", "install", "-y", "curl"]
不经过 shell 解析,参数必须用双引号,适合含空格或特殊字符的命令;环境变量需显式调用 shell:RUN ["sh", "-c", "echo $PATH"]
安装依赖的实用写法原则
避免“一条命令一个 RUN”,而是合并操作、及时清理:
- 把更新源、安装、清理放在同一行:RUN apt-get update && apt-get install -y nginx && rm -rf /var/lib/apt/lists/*
- 用 \ 换行保持可读性:RUN apt-get update && \
apt-get install -y python3-pip && \
rm -rf /var/lib/apt/lists/* - Alpine 系统用 apk:RUN apk add --no-cache curl jq
- 不要在 RUN 中写密码、密钥、token 等敏感信息——它们会留在镜像层里,哪怕后续删掉文件也难彻底清除
常见陷阱与替代思路
有些操作看似该用 RUN,其实有更优解:
- 单纯复制二进制文件,优先用 COPY 而非 curl + RUN 下载(更可重现、可校验)
- 需要复杂脚本逻辑,可先 COPY 脚本再 RUN 执行,比把长命令塞进 RUN 更易维护
- 多阶段构建中,只在 builder 阶段用 RUN 编译,最后阶段 COPY 成果,避免把编译工具链打进生产镜像
- 反复调试时,可临时加 RUN sh -c 'ls -l /usr/bin' 查看安装结果,但上线前应删掉这类诊断命令










