【问题标题】:Dockerfile: how to set env variable from file contentsDockerfile:如何从文件内容设置环境变量
【发布时间】:2019-01-09 13:15:35
【问题描述】:

我想在我的 Dockerfile 中设置一个环境变量。

我有一个如下所示的.env 文件: FOO=bar

在我的 Dockerfile 中,我有一个命令可以解析该文件的内容并将其分配给 FOO。

RUN 'export FOO=$(echo "$(cut -d'=' -f2 <<< $(grep FOO .env))")'

我遇到的问题是上面的脚本没有返回我需要的内容。事实上,它不会返回任何东西。

当我运行 docker-compose up --build 时,它会因为这个错误而失败。

The command '/bin/sh -c 'export FOO=$(echo "$(cut -d'=' -f2 <<< $(grep FOO .env))")'' returned a non-zero code: 127

我知道命令 /bin/sh -c 'echo "$(cut -d'=' -f2 <<< $(grep FOO .env))"' 会生成正确的输出,但我不知道如何将该输出分配给环境变量。

对我做错了什么有什么建议吗?

【问题讨论】:

  • 这里有几个问题。您想要在映像中设置这些变量,用于构建的其余部分,还是只需要一个运行命令?您是否将 .env 文件复制到图像中?除了 127 错误,您是否从构建中获得任何其他日志?
  • 我添加了文件(而不是副本)。我正在尝试设置一个容器范围的环境变量。
  • 在记录错误方面没有得到更多。
  • 请注意,<<< 不是 standard 重定向运算符,并且一些轻量级基础映像的 shell 实现的很少,不在标准中。

标签: shell docker docker-compose sh posix


【解决方案1】:

环境变量

如果你想在你的 docker 镜像中设置一些环境变量(在容器中使用),你可以简单地在你的 docker-compose.yml 文件中使用env_file 配置选项。使用该选项, .env 文件中的所有条目将被设置为映像中的环境变量,从而进入容器。

More Info about env_file


构建 ARGS

如果您的要求是仅在您的 Dockerfile 中使用某些变量,那么您可以按如下方式指定它们

ARG FOO
ARG FOO1
ARG FOO2

等等……

您必须在 docker-compose.yml 中的 build 键下指定这些参数

build:
  context: .
  args:
    FOO: BAR
    FOO1: BAR1
    FOO2: BAR2

More info about args


在 docker-compose.yml 文件中访问 .env 值

如果您正在考虑将一些值从 .env 传递到 docker-compose 文件中,那么您只需将 .env 文件放在与 docker-compose.yml 文件相同的位置,您可以如下设置配置值;

ports:
  - "${HOST_PORT}:80"

因此,作为示例,您可以通过在 .env 文件中设置服务的主机端口

Please check this

【讨论】:

    【解决方案2】:

    首先,您看到的错误。我怀疑问题中未包含“未找到”错误消息。如果是这种情况,那么第一个问题是您尝试运行一个完整字符串的可执行文件,因为您将其括在引号中。它不是试图运行 shell 命令“export”,而是试图找到一个包含空格的完整字符串的二进制文件。因此,要解决该错误,您需要取消引用 RUN 字符串:

    RUN export FOO=$(echo "$(cut -d'=' -f2 <<< $(grep FOO .env))")
    

    但是,这并不能解决您的根本问题。 RUN 命令的结果是 docker 将文件系统的更改保存为映像的新层。仅保存对文件系统的更改。您正在运行的 shell 命令会更改 shell 状态,但随后该 shell 退出,运行命令返回,并且该 shell 的状态(包括环境变量)消失了。

    要为您的应用程序解决这个问题,我可以想到两个选项:

    选项 A:为所有 .env 值注入构建参数到您的构建中,并编写一个调用构建的脚本,并为每个变量使用正确的 --build-arg 标志。在 Dockerfile 中,每个变量都有两行:

    ARG FOO1=default value1
    ARG FOO2=default value2
    ENV FOO1=${FOO1} \
        FOO2=${FOO2}
    

    选项 B:注入您的 .env 文件并使用容器中的入口点对其进行处理。这个入口点可以在启动实际应用程序之前运行您的导出命令。在需要这些变量的构建期间,您还需要为每个RUN 命令执行此操作。我用于将文件内容拉入环境变量的一种简写是:

    set -a && . .env && set +a
    

    【讨论】:

    • set...set 实际上是做什么的?
    • @andig 自动导出调用之间定义的任何变量。否则变量只定义在当前shell中,其他命令看不到。
    猜你喜欢
    • 2017-11-15
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    相关资源
    最近更新 更多