如何使用带有centos7 / httpd基本映像的Docker将EnvironmentFile指令添加到systemctl

时间:2016-05-21 17:49:17

标签: apache docker centos dockerfile systemd

我不确定在不创建自己的基本映像的情况下是否可行,但我在服务器上的/etc/environment中使用环境变量,并且通常通过执行以下操作使其可以访问apache:

$ printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
 >> /etc/environment
$ mkdir /usr/lib/systemd/system/httpd.service.d
$ printf "[Service]\n\
EnvironmentFile=/etc/environment"\
 > /usr/lib/systemd/system/httpd.service.d/environment.conf
$ systemctl daemon-reload
$ systemctl restart httpd
$ reboot

然后,在getenv('HTTP_VAR1');等的任何PHP调用中都可以使用变量。但是,在从docker文件运行时,我在systemctl命令上得到了dbus错误。如果没有systemctl命令,似乎变量不可用于apache,因为新的EnvironmentFile指令似乎没有生效。我的docker文件片段:

FROM centos/httpd:latest

RUN printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
 >> /etc/environment

RUN mkdir /usr/lib/systemd/system/httpd.service.d &&\
 printf "[Service]\n\
EnvironmentFile=/etc/environment"\
 > /usr/lib/systemd/system/httpd.service.d/environment.conf

RUN systemctl daemon-reload &&\
 systemctl restart httpd

COPY entrypoint.sh /entrypoint.sh

1 个答案:

答案 0 :(得分:1)

所以我今天碰巧回答了这个问题。似乎systemd在单引号内删除反斜杠,但它也可能影响我在测试中看到的双引号。我找到了systemd development mailing list thread from April 2014 where patching the issue was being discussed。似乎修复从未进入过。所以我们必须解决它。

在尝试解决它时,我注意到实际上读取变量的一些问题。似乎Apache或者php-cli都会获得正确的变量,有时根本没有,它需要一些调查来弄清楚发生了什么。然后我开始阅读systemd's EnvironmentFile directive,看看是否还有更多内容可以从文档中获得。事实证明它不评估bash所以导出不起作用。它期望一个带有变量赋值的文本文件,这是可能使其无法解决的主要问题之一。

然后,我设计了一个可行的解决方案。利用systemd's ExecStartPre directive我可以在启动httpd服务时运行脚本。然后我读入环境文件并编写一个新的纯文本,然后由httpd的systemd单元使用。这是代码:

首先,我将变量移动到/etc/profile.d/目录而不是/etc/environment文件。

档案: /etc/profile.d/environment.sh
这是我们存储所有环境变量的地方,这可以在所有交互式shell登录中轻松获取。在极少数情况下,我们需要以非交互方式提供这些变量,我们可以向--login提供/bin/bash标记或手动提供。

export HTTP_VAR1=var1-value-with-a-back\slash
export HTTP_VAR2=var2-value

档案: /usr/lib/systemd/system/httpd.service.d/environment.conf
我们的drop-in单元文件扩展了httpd服务的工作方式。我添加了一个在httpd启动之前运行的脚本。这将在所有httpd重启上运行并启动。运行的脚本在/etc/profile.d/environment.env生成一个纯文本文件,我们随后告诉systemd加载为EnvironmentFile。

[Service]
ExecStartPre=/usr/bin/bash -c "/usr/local/bin/generate-plain-environment-file"
EnvironmentFile=/etc/profile.d/environment.env

档案: /usr/local/bin/generate-plain-environment-file
这是我正在使用的剧本,我把它快速地鞭打在一起,我真的不认为它是那么健壮,它可能会更好。它只是从行的开头删除export然后转义任何反斜杠,因为systemd会删除单个反斜杠。更合适的解决方案可能是使用bash来评估每一行,并在实际bash变量中使用变量或其他bash时获取变量值,然后将它们输出为纯文本name = value赋值,但这不是我的用例所以我没有打扰。

#!/bin/bash

cd /etc/profile.d/
rm -rf "./environment.env"

while IFS='' read -r line || [[ -n "$line" ]]; do
  echo $(echo "${line}" | sed 's/^export //' | sed 's/\\/\\\\/g') >> "./environment.env";
done < "./environment.sh"

档案: /etc/profile.d/environment.env
这是由描述的脚本生成的结果文件。

HTTP_VAR1=var1-value-with-a-back\\slash
HTTP_VAR2=var2-value

结论是我现在有两个文件同样的东西但我只需要维护一个,另一个是每次重启httpd时生成的。此外,我们在此过程中修复了反斜杠问题。乌拉!