【问题标题】:Docker/Compose: Define and use env variableDocker/Compose:定义和使用环境变量
【发布时间】:2019-02-02 10:40:34
【问题描述】:

在我的 github 上,我正在从一个 debian 最小 docker 映像创建一个小分支。它实际上是在以前的基础上构建的 5 个包:

debian-base-minimal
debian-base-standard
debian-base-security
debian-base-apache
debian-base-apache-php

在 debian-base-apache 上,我想获得一个工作环境变量,我可以稍后在 docker-compose 文件中定义它。环境应该做什么?

如果通过 docker-compose 定义,它应该在 /etc/apache2/apache2.conf 的末尾写入 ServerName $SERVER_NAME 以设置全局服务器名称。如果为空,则不应写入新行。

但是为什么它在空的时候什么也不写呢? Cauz 在将 Dockerfile 构建到映像时不应包含 SERVER_NAME

我已经尝试过类似的方法: echo "ServerName $SERVER_NAME" >> /etc/apache2/apache2.conf

在我的 040-debian-base-apache 文件上。但是在构建它所写的ServerName 时,因为我没有定义一个值并且它使用null。如果我在 Dockerfile (ENV SERVER_NAME=127.0.0.1) 中设置默认值,它会使用 127.0.0.1 构建映像,并且我无法通过变量更改 127.0.0.1,因为变量已经填充了该值。

在 Dockerfile 中定义 ENV SERVER_NAME=127.0.0.1 的建筑物的输出(实际上不在 repo 中):

[...]
+ echo 'ServerName 127.0.0.1'
+ /etc/init.d/apache2 stop
Stopping Apache httpd web server: apache2.
ok.
+ /etc/init.d/apache2 start
Starting Apache httpd web server: apache2.
ok.
[...]

没关系,如果有默认的 127.0.0.1 因为 apache 可以启动。但我现在无法在 docker-compose.yml 中定义它,因为它的硬编码 127.0.0.1 而不是变量的输出。

关于在 Dockerfile 中没有定义 ENV 的建筑物的输出(实际上是 repo 版本):

[...]
+ echo 'ServerName '
+ /etc/init.d/apache2 stop
Stopping Apache httpd web server: apache2.
+ /etc/init.d/apache2 start
Starting Apache httpd web server: apache2 failed!
The apache2 configtest failed. ... (warning).
Output of config test was:
AH00526: Syntax error on line 228 of /etc/apache2/apache2.conf:
ServerName takes one argument, The hostname and port of the server 
[...]

谁能帮我解决这个问题?很高兴了解它是如何工作的。

非常感谢。

【问题讨论】:

  • 请分享到您的 github 分支的链接,以便我们可以看到您在 Dockerfile 和 docker compose 文件中的内容。请将其添加到问题中,并分享您用于运行它们的命令。
  • 正如我在评论中所说,请将链接添加到您的问题以及用于运行它们的命令。
  • @Exadra37 我编辑了我的顶级帖子,其中包含更多信息、链接、输出以及我使用哪个文件构建所有东西。你还需要什么别的吗?很抱歉,但我不知道你对 add the link to your question 的明确含义

标签: apache docker debian


【解决方案1】:

正如您所观察到的,Dockerfile 中的每个 RUN 命令都发生在 docker build 时间,特别是文件的内容将根据您运行构建时的环境变量进行修复。您希望它根据变量的运行时值进行更改,这意味着您需要编写一个在启动时运行的脚本来执行此操作。

一种典型的方法是编写一个 ENTRYPOINT 脚本来进行首次设置。 ENTRYPOINT 作为命令行参数传递给 CMD(或传递给 docker run 的任何命令),因此如果它以 exec "$@" 结尾,它所做的最后一件事就是启动“正常”命令。你可以在这里使用任何普通的shell脚本逻辑,所以我可能会写

#!/bin/sh
if [ -n "$SERVER_NAME" ]; then
  echo "ServerName $SERVER_NAME" >> /etc/apache2/apache2.conf
fi
exec "$@"

然后你可以在你的 Dockerfile 中提供这个

COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["apachectl", "-DFOREGROUND"]

(如果您可以保证该文件在您的非 Windows 主机上具有执行权限,则不需要 chmodENTRYPOINT 必须使用 JSON 格式。如果您有另一个构建在这个,记住组合图像只有一个入口点和一个 CMD;你建议的非常深的图像堆栈是一个非常不寻常的设置。)

【讨论】:

  • 非常感谢您的帮助。现在我明白它应该如何工作了:) the very deep stack of images you suggest is a pretty unusual setup 你能解释一下你的意思吗?你的意思是图像的依赖来运行 apache-php 还是你的意思只是像 php 扩展等?
  • 我见过的大多数项目(即使是商业生产环境中的项目)只有一两个级别的图像。实际添加任何特定于应用程序的代码之前的五个级别的图像似乎过于复杂。例如,在您的存储库中,(复杂的)“最小”层中没有任何东西是 Docker 映像通常或必需的。
  • 例如,最好将最小的、标准的、安全的图像合并到一个图像中并进行一些清理,这样我以后就拥有了新的 debian-base-minimal,这是应用程序的依赖项像 apache、apache 代理等,而不是最小基础、标准、安全标准基础、应用程序安全基础(在本例中为 apache)?
猜你喜欢
  • 2015-06-17
  • 2019-07-26
  • 2019-12-18
  • 2017-06-18
  • 1970-01-01
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 2022-01-01
相关资源
最近更新 更多