dockerfile 中 shell 变量不可直接使用,需通过 arg(构建期传参)、env(运行时环境变量)和 entrypoint.sh 脚本协同实现动态逻辑;arg 不留存镜像,env 可被覆盖,启动脚本支持条件判断与配置替换。

在 Dockerfile 中直接使用 Shell 变量(比如 $VAR)是行不通的,因为 Docker 构建过程不执行 Shell 解释器——它只解析指令本身。真正能实现“动态构建逻辑”的,是通过 ARG、ENV、构建时命令替换和运行时 Shell 脚本协同完成的。
用 ARG 传入构建期参数
ARG 是唯一专为构建阶段设计的变量机制,它允许你在 docker build 时传入值,并在 RUN 指令中被 Shell 使用(前提是该指令以 Shell 形式执行)。
- 在 Dockerfile 中声明:
ARG VERSION或ARG APP_ENV=prod(支持默认值) - 构建时传参:
docker build --build-arg VERSION=2.4.1 -t myapp . - 在 RUN 中使用:
RUN echo "Building for $VERSION" && ./configure --version=$VERSION - 注意:
ARG不会保留在最终镜像中,也不能被后续容器运行时读取
用 ENV 设置运行时环境变量
ENV 定义的变量会写入镜像层,对容器启动后所有进程可见,包括你写的启动脚本。
- 可直接赋值:
ENV NODE_ENV=production - 可引用 ARG:
ARG BUILD_TIME→ENV BUILD_TIME=$BUILD_TIME - 支持 Bash 风格扩展:
ENV PATH="/app/bin:$PATH",或带默认值:ENV LOG_LEVEL=${LOG_LEVEL:-info} - 容器启动时可用
-e LOG_LEVEL=debug覆盖 ENV 值
在启动脚本里读取并处理变量
把动态逻辑下沉到容器启动时的 Shell 脚本中,是最灵活、最常用的方式。
- 编写
entrypoint.sh,开头加#!/bin/sh,然后用${VAR:-default}安全取值 - COPY 并赋予执行权限:
COPY entrypoint.sh /usr/local/bin/→RUN chmod +x /usr/local/bin/entrypoint.sh - 用
ENTRYPOINT ["entrypoint.sh"]启动,脚本内可做条件判断、文件生成、配置替换等 - 例如:
if [ "$APP_ENV" = "dev" ]; then cp /config/dev.conf /app/config.conf; fi
避免常见陷阱
很多“变量不生效”的问题,其实源于对分层构建和 Shell 上下文的理解偏差。
-
RUN export VAR=value无效:变量只在当前RUN层临时存在,不会传递给下一层 -
ENV VAR=$OTHER中$OTHER必须是已定义的ARG或之前定义的ENV,不能是运行时才有的值 -
CMD ["echo", "$VAR"]不会展开变量:exec 格式绕过 Shell,应改用CMD echo "$VAR"(Shell 格式)或在脚本中处理 - Windows 路径中反斜杠可能被误解析,建议显式设置
# escape=`解析器指令











