【问题标题】:issues in accessing docker environment variables in systemd service files在 systemd 服务文件中访问 docker 环境变量的问题
【发布时间】:2019-03-05 09:50:51
【问题描述】:

1) 我正在使用以下 cmd 运行 docker 容器(使用 -e 选项传递一些环境变量)

$ docker run --name=xyz -d -e CONTAINER_NAME=xyz -e SSH_PORT=22 -e NWMODE=HOST -e XDG_RUNTIME_DIR=/run/user/0 --net=host -v /mnt:/mnt -v /dev:/dev -v /etc/sysconfig/network-scripts:/etc/sysconfig/network-scripts -v /:/hostroot/ -v /etc/hostname:/etc/host_hostname -v /etc/localtime:/etc/localtime -v /var/run/docker.sock:/var/run/docker.sock --privileged=true cf3681e04bfb

2) 如上运行容器后,我检查容器内的环境变量 NWMODE,它正确显示如下:

$ docker exec -it xyz bash $ env | grep NWMODE NWMODE=HOST

3) 现在,我创建了一个示例服务“b”,如下所示,它执行脚本 b.sh(我尝试访问 NWMODE):

root@ubuntu16:/etc/systemd/system# cat b.service
[Unit]
Description=testing service b

[Service]
ExecStart=/bin/bash /etc/systemd/system/b.sh

root@ubuntu16:/etc/systemd/system# cat b.sh
#!/bin/bash`
systemctl import-environment
echo "NWMODE:" $NWMODE`

4) 现在,如果我启动服务 'b' 并查看其日志,则表明它无法访问 NWMODE 环境变量

$ systemctl start b
$ journalctl -fu b
...
systemd[1]: Started testing service b.
bash[641]: NWMODE:      //blank for $NWMODE here`

5) 现在不是在 b.sh 中使用“systemctl import-environment”,如果我执行以下操作,那么 b.service 日志会显示 NWMODE env 变量的正确值: $ systemctl import-environment $ systemctl start b

虽然上面的第 5 步有效,但我不能这样做,因为我系统中的所有服务都将由 systemd 自动启动。在这种情况下,谁能告诉我如何访问服务文件中的环境变量(使用上面的 'docker run...' cmd 传递)(例如上面的 b.sh)。这可以通过systemctl import-environment 以某种方式实现吗?还是有其他方法?

【问题讨论】:

  • 您确定在设置环境变量之前您的服务没有启动吗?我敢打赌它是。如果是这种情况,您需要为 systemd 创建一些依赖项,以便它在适当的时间启动。
  • @mrunion :在我运行docker run... cmd 的那一刻设置环境变量。在上面的示例中,我正在尝试手动运行该服务。甚至在手动运行服务之前,我已经在上面展示了 env 变量存在。

标签: docker ubuntu-16.04 systemd


【解决方案1】:

systemd 取消设置所有环境变量以提供干净的环境。旨在成为安全功能的 Afaik。

解决方法:创建文件/etc/systemd/system.conf.d/myenvironment.conf

[Manager]
DefaultEnvironment=CONTAINER_NAME=xyz NWMODE=HOST XDG_RUNTIME_DIR=/run/user/0

systemd 会设置这个文件中声明的环境变量。

您可以设置一个ENTRYPOINT 脚本,在运行systemd 之前自动创建此文件。示例:

RUN echo '#! /bin/bash \n\
echo "[Manager] \n\
DefaultEnvironment=$(while read -r Line; do echo -n "$Line" ; done < <(env) \n\
" >/etc/systemd/system.conf.d/myenvironment.conf \n\
exec /lib/systemd/systemd \n\
' >/usr/local/bin/setmyenv && chmod +x /usr/bin/setmyenv

ENTRYPOINT /usr/bin/setmyenv

您可以将其存储在外部并使用COPY 添加,而不是在Dockerfile 中创建脚本:

#! /bin/bash
echo "[Manager]
DefaultEnvironment=$(while read -r Line; do echo -n "$Line" ; done < <(env)
" >/etc/systemd/system.conf.d/myenvironment.conf
exec /lib/systemd/systemd

【讨论】:

    【解决方案2】:

    TL;DR

    使用 bash 运行命令,首先将 docker 环境变量存储到一个文件中(或者将它们通过管道传输两个 awk),提取并导出导出变量,最后运行您的主脚本。

    ExecStart=/bin/bash -c "cat /proc/1/environ | tr '\0' '\n' > /home/env_file; export MY_ENV_VARIABLE=$(awk -F= -v key="MY_ENV_VARIABLE" '$1==key {print $2}' /home/env_file); /usr/bin/python3 /usr/bin/my_python_script.py"
    
    

    无论@mviereck 说的是真的,我仍然找到了解决这个问题的另一种方法。

    我的用例是在 Docker 运行命令 (docker run -e MY_ENV_VARIABLE="some_val") 中将环境变量传递给我的 system-d 容器,并在通过 system-d 单元文件运行的 python 脚本中使用它。

    根据这篇文章(https://forums.docker.com/t/where-are-stored-the-environment-variables/65762),容器环境变量可以在容器内的运行进程/proc/1/environ中找到。执行cat 确实表明环境变量MY_ENV_VARIABLE=some_val 确实存在,尽管形式有些混乱。

    $ cat /proc/1/environ
    
    HOSTNAME=271fbnd986bdMY_ENV_VARIABLE=some_valcontainer=dockerLC_ALL=CDEBIAN_FRONTEND=noninteractiveHOME=/rootroot@271fb0d986bd
    

    现在的主要任务是提取MY_ENV_VARIABLE="some_val" 值并将其传递给system-d 单元文件中的ExecStart 指令。

    (提取代码引用自How to grep for value in a key-value store from plain text

    # this outputs a nice key,value pair
    $ cat /proc/1/environ | tr '\0' '\n'
    
    HOSTNAME=861f23cd1b33
    MY_ENV_VARIABLE=some_val
    container=docker
    LC_ALL=C
    DEBIAN_FRONTEND=noninteractive
    HOME=/root
    
    # we can store this in a file for use, too
    $ cat /proc/1/environ | tr '\0' '\n' > /home/env_var_file
    
    # we can then reuse the file to extract the value of interest against a key
    $ awk -F= -v key="MY_ENV_VARIABLE" '$1==key {print $2}' /home/env_file
    
    some_val
    
    

    现在在 system-d 单元文件的ExecStart 指令中,我们可以这样做:

    [Service]
    Type=simple
    ExecStart=/bin/bash -c "cat /proc/1/environ | tr '\0' '\n' > /home/env_file; export MY_ENV_VARIABLE=$(awk -F= -v key="MY_ENV_VARIABLE" '$1==key {print $2}' /home/env_file); /usr/bin/python3 /usr/bin/my_python_script.py"
    
    

    【讨论】:

      猜你喜欢
      • 2019-08-02
      • 2021-05-19
      • 1970-01-01
      • 1970-01-01
      • 2020-06-23
      • 1970-01-01
      • 2020-01-24
      • 1970-01-01
      • 2020-02-07
      相关资源
      最近更新 更多