320

我正在为 ruby​​ 应用程序构建一个容器。我的应用程序的配置包含在环境变量中(使用dotenv加载到应用程序中)。

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

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

我尝试了几件事。

ENV REQUEST_DOMAIN $REQUEST_DOMAIN
ENV REQUEST_DOMAIN `REQUEST_DOMAIN`

一切都传递“REQUEST_DOMAIN”字符串而不是环境变量的值。有没有办法将环境变量值从主机传递到容器?

4

7 回答 7

508

你应该在你的 Dockerfile 中使用该ARG指令来达到这个目的。

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

所以你的Dockerfile会有这一行:

ARG request_domain

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

ARG request_domain=127.0.0.1

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

ENV request_domain=$request_domain

然后你将像这样构建你的容器:

$ docker build --build-arg request_domain=mydomain Dockerfile


注意 1:如果您ARG在 Dockerfile 中引用了 an 但在--build-arg.

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

[警告] 一个或多个构建参数 [foo] 未使用。

于 2016-01-04T21:23:22.263 回答
62

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

然后有一个类似于以下内容的 Dockerfile:

ENV MY_ENV_VAR $MY_ENV_VAR

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

于 2014-01-27T18:13:44.487 回答
20

在不失去使用orenvsubst之类命令的能力且不使用中间文件的情况下使用 Bash 的Process Substitution的替代方法是:COPYADD

docker build -f <(envsubst < Dockerfile) -t my-target .
于 2017-03-13T18:56:52.080 回答
15

从您在运行时创建的文件中加载环境变量。

export MYVAR="my_var_outside"
cat > build/env.sh <<EOF
MYVAR=${MYVAR}
EOF

...然后在 Dockerfile

ADD build /build
RUN /build/test.sh

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

#!/bin/bash
. /build/env.sh
echo $MYVAR > /tmp/testfile
于 2015-03-19T22:57:57.273 回答
8

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

services:
  web:
    build:
      context: ./api
      dockerfile: Dockerfile
      args:
        - SECRET_KEY=$SECRET_KEY
        - DATABASE_URL=$DATABASE_URL
        - AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID

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

SECRET_KEY=blahblah
DATABASE_URL=dburl

现在,当您运行 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}

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

于 2021-09-14T07:34:26.467 回答
5

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

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

于 2017-10-31T19:30:54.727 回答
-7

添加-e用于将环境变量传递给容器的密钥。例子:

$ MYSQLHOSTIP=$(sudo docker inspect -format="{{ .NetworkSettings.IPAddress }}" $MYSQL_CONRAINER_ID)
$ sudo docker run -e DBIP=$MYSQLHOSTIP -i -t myimage /bin/bash

root@87f235949a13:/# echo $DBIP
172.17.0.2
于 2014-01-26T20:45:07.657 回答