我们可以在通过 dockerfile 构建 docker 映像的同时通过 cmd 行传递 ENV 变量吗?

Posted

技术标签:

【中文标题】我们可以在通过 dockerfile 构建 docker 映像的同时通过 cmd 行传递 ENV 变量吗?【英文标题】:Can we pass ENV variables through cmd line while building a docker image through dockerfile? 【发布时间】:2015-09-20 19:47:46 【问题描述】:

我正在处理一项任务,该任务涉及使用 Dockerfile 构建一个以 centOs 为基础的 docker 映像。 dockerfile 中的步骤之一需要设置 http_proxyhttps_proxy ENV 变量才能在代理后面工作。

由于这个 Dockerfile 将被具有不同代理的多个团队使用,我想避免必须为每个团队编辑 Dockerfile。相反,我正在寻找一种允许我在构建时传递 ENV 变量的解决方案,例如,

sudo docker build -e http_proxy=somevalue .

我不确定是否已经有提供此功能的选项。我错过了什么吗?

【问题讨论】:

在运行时传递这些有什么问题?像docker run -e http_proxy http://1.2.3.4:3128 -e https_proxy 1.2.3.4:3129 这样的东西? docker rundocs.docker.com/reference/commandline/run的文档 问题是 docker 文件中的其中一个步骤涉及 yum 安装,如果我不设置 http/https ENV 变量并且没有正确安装,我无法构建图像。所以 docker run 在这里帮不了我。 恐怕您必须构建特定的图像,唯一的区别是 http_proxy(s) ONBUILD 的值可能会有所帮助,但恐怕它不适合这里,请参阅文档docs.docker.com/reference/builder 这已经在这里github.com/docker/docker/issues/4962 和github.com/docker/docker/pull/9176 讨论过并关闭,所以目前看来你没有解决方案 感谢 user2915097 提供的 cmets。我已经浏览了上面的 github 链接,我问这个问题是希望 *** 上的某个人可能遇到过类似的情况。 【参考方案1】:

可以使用build arguments(在 Docker 1.9+ 中)构建容器,其工作方式类似于环境变量。

方法如下:

FROM php:7.0-fpm
ARG APP_ENV=local
ENV APP_ENV $APP_ENV
RUN cd /usr/local/etc/php && ln -sf php.ini-$APP_ENV php.ini

然后构建一个生产容器:

docker build --build-arg APP_ENV=prod .

针对您的特定问题:

FROM debian
ENV http_proxy $http_proxy

然后运行:

docker build --build-arg http_proxy=10.11.24.31 .

请注意,如果您使用docker-compose 构建容器,则可以specify these build-args in the docker-compose.yml file,但不能在命令行上。但是,您可以使用variable substitution in the docker-compose.yml file, which uses environment variables。

【讨论】:

因为我忽略了它:您需要 ARG 告诉 docker 可以将构建参数传递给构建器。如果不指定 ARG ,它将不起作用。 不需要这个ENV APP_ENV $APP_ENV。有ARG APP_ENV 没有=local 就足够了,它将获取构建参数并将其用作ENV 设置的任何变量 @ElmoVanKielmo 在构建过程中确实如此,但在运行 docker 映像时,ARG 不会作为环境变量持续存在。使用ENV APP_ENV $APP_ENV 可以确保在容器运行时环境变量仍然可用。 @DuckPuppy 是的,但我坚持 OP 的问题 @ElmoVanKielmo OP 的问题是关于从命令行传递ENV,那么单独使用ARG 有什么帮助?您需要ARG,以便您可以通过--build-arg 传递一个,然后您需要ENV 将其复制到环境变量以与图像一起保存。【参考方案2】:

我遇到了同样的情况。

根据 Sin30 的回答,漂亮的解决方案是使用 shell,

CMD ["sh", "-c", "cd /usr/local/etc/php && ln -sf php.ini-$APP_ENV php.ini"]

【讨论】:

【参考方案3】:

所以我不得不通过反复试验来解决这个问题,因为很多人解释说你可以通过 ARG -> ENV 但它并不总是有效,因为 ARG 是在FROM 标签。

下面的例子应该清楚地解释这一点。我最初的主要问题是我所有的 ARGS 都是在 FROM 之前定义的,这导致所有 ENV 总是未定义。

# ARGS PRIOR TO FROM TAG ARE AVAIL ONLY TO FROM for dynamic a FROM tag
ARG NODE_VERSION
FROM node:$NODE_VERSION-alpine

# ARGS POST FROM can bond/link args to env to make the containers environment dynamic
ARG NPM_AUTH_TOKEN
ARG EMAIL
ARG NPM_REPO

ENV NPM_AUTH_TOKEN $NPM_AUTH_TOKEN
ENV EMAIL $EMAIL
ENV NPM_REPO $NPM_REPO

# for good measure, what do we really have
RUN echo NPM_AUTH_TOKEN: $NPM_AUTH_TOKEN && \
  echo EMAIL: $EMAIL && \
  echo NPM_REPO: $NPM_REPO && \
  echo $HI_5
# remember to change HI_5 every build to break `docker build`'s cache if you want to debug the stdout

..... # rest of whatever you want RUN, CMD, ENTRYPOINT etc..

【讨论】:

哇,该死,我也遇到了!没有人谈论这个,文档中没有提到,警告等!非常感谢!!! 如果您的部署环境来自自动 CI,我可能会提到这很关键。 IE 当我试图让 gitlab CI 跨项目域进行扩展时,我发现了这一点。 IE 一个项目可能正在解决一个不同的节点版本等... 让我省了些力气,谢谢!我永远不会想到 ARG 的位置很重要.. 我觉得这个其实解释了here:An ARG declared before a FROM is outside of a build stage, so it can’t be used in any instruction after a FROM

以上是关于我们可以在通过 dockerfile 构建 docker 映像的同时通过 cmd 行传递 ENV 变量吗?的主要内容,如果未能解决你的问题,请参考以下文章

翻译Dockerfile参考

02 . DockerFile构建镜像和Docker仓库

Dockerfile构建镜像与部署

Dockerfile

通过dockerfile从零构建centos7.4镜像

使用Dockerfile定制自己的docker镜像