获取Dockerfile中的环境变量值

Dam*_*IEU 236 docker

我正在为一个红宝石应用程序构建容器.我的应用程序配置包含在环境变量中(使用dotenv加载到应用程序内).

其中一个配置变量是app的公共ip,它在内部用于建立链接.我需要添加一个dnsmasq条目,将此ip指向容器内的127.0.0.1,这样它就可以获取应用程序的链接,就好像它不是容器化的一样.

因此ENV,我试图在我的Dockerfile中设置一个将环境变量传递给容器的文件.

我试了几件事.

ENV REQUEST_DOMAIN $REQUEST_DOMAIN
ENV REQUEST_DOMAIN `REQUEST_DOMAIN`
Run Code Online (Sandbox Code Playgroud)

但是,所有内容都传递了"REQUEST_DOMAIN"字符串,而不是环境变量的值.有没有办法将环境变量值从主机传递到容器?

Dan*_*men 363

您应该在Dockerfile中使用该ARG指令,该指令用于此目的.

ARG指令定义了一个变量,用户可以使用--build-arg <varname>=<value>标志使用docker build命令在构建时将该变量传递给构建器.

所以你的Dockerfile将有这一行:

ARG request_domain
Run Code Online (Sandbox Code Playgroud)

或者如果您更喜欢默认值:

ARG request_domain=127.0.0.1
Run Code Online (Sandbox Code Playgroud)

现在您可以在Dockerfile中引用此变量:

ENV request_domain=$request_domain
Run Code Online (Sandbox Code Playgroud)

那么你将构建你的容器,如下所示:

$ docker build --build-arg request_domain=mydomain Dockerfile
Run Code Online (Sandbox Code Playgroud)


注意1:如果您ARG在Dockerfile中引用了一个但是将其排除在外,则不会构建您的映像--build-arg.

注意2:如果用户指定了未在Dockerfile中定义的构建参数,则构建会输出警告:

[警告]未使用一个或多个build-args [foo].

  • ARG可从docker v1.9开始提供. (12认同)
  • ENV 线的目的是什么?对我来说 --build-arg + ARG 就足够了。 (5认同)
  • ```如果您在Dockerfile中引用了ARG但在--build-arg``中将其排除在外,那么您的图像将无法构建.即使没有--build-arg,您也可以使用引用构建映像.此外,您可以为构建arg设置默认值. (4认同)
  • ARG定义了在后续命令中的dockerfile内部使用的变量。ENV定义了一个环境变量,该变量被传递给容器。 (2认同)
  • 请注意,在 Windows 和 Linux 上,Dockerfile 本身都需要使用 `$var` 语法的变量...在 Windows 上使用 `RUN` 命令时,cmd 仍然需要 `%var%` 语法,并且 powershell 仍然会使用 `%var%` 语法。期待 `$env:var` 语法。 (2认同)

Zin*_*fan 68

这适用于那些希望在构建期间使用文件从docker-compose传递 env 变量到dockerfile ,然后将这些参数作为 env 变量传递到容器的人。典型的 docker-compose 文件.env

services:
  web:
    build:
      context: ./api
      dockerfile: Dockerfile
      args:
        - SECRET_KEY=$SECRET_KEY
        - DATABASE_URL=$DATABASE_URL
        - AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
Run Code Online (Sandbox Code Playgroud)

将文件中存在的 env 变量传递.env给构建命令中的 args。典型.env文件

SECRET_KEY=blahblah
DATABASE_URL=dburl
Run Code Online (Sandbox Code Playgroud)

现在,当您运行 docker-compose up -d 命令时,docker-compose 文件将从 .env 文件中获取值,然后将其传递给 docker-compose 文件。现在,Web 的 Dockerfile 在构建过程中通过 args 包含所有这些变量。现在典型的web dockerfile,

FROM python:3.6-alpine

ARG SECRET_KEY
ARG DATABASE_URL
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
ARG AWS_BUCKET
ARG AWS_REGION
ARG CLOUDFRONT_DOMAIN

ENV CELERY_BROKER_URL redis://redis:6379/0
ENV CELERY_RESULT_BACKEND redis://redis:6379/0
ENV C_FORCE_ROOT true
ENV SECRET_KEY  ${SECRET_KEY?secretkeynotset}
ENV DATABASE_URL ${DATABASE_URL?envdberror}
Run Code Online (Sandbox Code Playgroud)

现在我们收到了这些 Secret_key 和 db url 作为 dokcerfile 中的 arg。现在让我们在ENVas中使用它们ENV SECRET_KEY ${SECRET_KEY?secretkeynotset}。现在甚至 docker 容器的环境中也有这些变量。 记住不要使用ARG $SECRET_KEY(我就是这么做的)。它应该是ARG SECRET_KEY

  • @MaximColesnic你的args应该在build部分下,而不是在你的错误所说的web下。所以 args 位于 services.web.build 下。注意你的缩进。 (4认同)
  • 感谢这个定义明确的答案 (2认同)

jon*_*sfj 56

所以你可以这样做: cat Dockerfile | envsubst | docker build -t my-target -

然后有一个Dockerfile,类似于:

ENV MY_ENV_VAR $MY_ENV_VAR
Run Code Online (Sandbox Code Playgroud)

我想一些特殊字符可能存在问题,但这至少适用于大多数情况.

  • 如果您需要从包含Dockerfile的目录中添加ADD文件,这似乎不起作用. (13认同)
  • 回复@ TomHennen的评论,如果你想在你的Dockerfile中使用像COPY这样的依赖于上下文的命令,你总是可以将envsubst的输出重定向到一个临时文件,然后将其输入到"docker build"中.示例:`cat Dockerfile | envsubst> DockerfileWithEnvVars`,然后`docker build -t my-target -f DockerfileWithEnvVars .`,然后`rm DockerfileWithEnvVars` (4认同)
  • 很好的解决方案!在Mac上,您可以将`envsubst`作为`brew install gettext`的一部分.但由于可能与BSD构建系统发生冲突,因此它只是"keg-only"并且没有制作symlnks.但是,可以安全地使用`ln -s/usr/local/Cellar/gettext/*/bin/envsubst/usr/local/bin /`将一个命令添加到PATH中.(这真的是关注的库.)或者你可以在`/ usr/local/Cellar/gettext/*/bin/envsubst`位置使用它 (2认同)
  • 为了澄清@TomHennen 的评论,将 Dockerfile 管道传递到 `docker build -` 是特别地,当您从 Dockerfile 引用相对路径时,无论 env var 替换如何,什么都不起作用。 (2认同)

小智 18

使用替代envsubst,而不会失去使用像命令的能力COPYADD,并且不使用中间文件是使用bash的进程替换:

docker build -f <(envsubst < Dockerfile) -t my-target .
Run Code Online (Sandbox Code Playgroud)

注意:最初想为jonasfj的答案添加评论,但似乎我没有足够的声誉.

  • 不幸的是,这似乎不起作用(Docker 17.09),我收到错误消息“无法准备上下文:Dockerfile(/ dev / fd / 63)必须在构建上下文中”。 (3认同)

小智 11

从运行时创建的文件加载环境变量.

export MYVAR="my_var_outside"
cat > build/env.sh <<EOF
MYVAR=${MYVAR}
EOF
Run Code Online (Sandbox Code Playgroud)

...然后在Dockerfile中

ADD build /build
RUN /build/test.sh
Run Code Online (Sandbox Code Playgroud)

其中test.sh从env.sh加载MYVAR

#!/bin/bash
. /build/env.sh
echo $MYVAR > /tmp/testfile
Run Code Online (Sandbox Code Playgroud)


sna*_*ssr 5

如果您只想查找并替换 Dockerfile 中的所有环境变量 ($ExampleEnvVar),然后构建它,这将起作用:

envsubst < /path/to/Dockerfile | docker build -t myDockerImage . -f -


gou*_*oup 5

当使用build-arg...

\n
\n

docker build --build-arg CODE_VERSION=1.2 Dockerfile

\n
\n

...考虑到该变量在以下之后不可用FROM

\n
ARG  CODE_VERSION=latest\nFROM base:${CODE_VERSION}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

ARG在 a 之前声明的 a位于FROM构建阶段之外,因此它不能在 a 之后的任何指令中使用\xe2\x80\x99 FROM

\n
\n

一般来说,如果不需要,ARG则应将 s 放在以下期间之后:FROMFROM

\n
FROM base:xy\nARG  ABC=123\n
Run Code Online (Sandbox Code Playgroud)\n
\n

ARG要使用在第一次FROM使用ARG构建阶段内没有值的指令之前声明的默认值:

\n
\n
ARG VERSION=latest\nFROM busybox:$VERSION\nARG VERSION\nRUN echo $VERSION > image_version\n
Run Code Online (Sandbox Code Playgroud)\n

https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact

\n