You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在基于systemd的Ubuntu Docker镜像中加载环境变量?

解决systemd服务无法获取Docker环境变量的问题

我之前也踩过一模一样的坑——systemd作为Docker容器的PID 1启动时,会初始化一个完全独立的环境,根本不会继承Dockerfile里定义的或者docker run时传递的环境变量。用runuser -l试图通过登录shell加载变量之所以没用,是因为登录shell读取的是系统默认的profile配置(比如/etc/profile、~/.profile),这些配置里根本没有Docker注入的变量。

下面给你两个实用的解决方案,按需选择:

方案一:将Docker环境变量持久化到登录shell配置中

我们可以在启动systemd之前,把/proc/1/environ里的变量写入到系统级的profile脚本里,这样任何登录shell(包括runuser -l启动的)都会自动加载这些变量。

修改你的Dockerfile如下:

FROM ubuntu-systemd
ENV VNC_PW="some-password"

# 创建一个脚本,把/proc/1/environ的变量导入到profile.d
RUN echo '#!/bin/bash' > /usr/local/bin/import-docker-env.sh && \
    echo 'while IFS= read -r -d "" env_var; do' >> /usr/local/bin/import-docker-env.sh && \
    echo '  # 只导入合法的环境变量(避免无效行)' >> /usr/local/bin/import-docker-env.sh && \
    echo '  if [[ "$env_var" =~ ^[A-Z_]+= ]]; then' >> /usr/local/bin/import-docker-env.sh && \
    echo '    echo "export $env_var" >> /etc/profile.d/docker-env.sh' >> /usr/local/bin/import-docker-env.sh && \
    echo '  fi' >> /usr/local/bin/import-docker-env.sh && \
    echo 'done < /proc/1/environ' >> /usr/local/bin/import-docker-env.sh && \
    chmod +x /usr/local/bin/import-docker-env.sh

# 先执行导入脚本,再启动systemd
ENTRYPOINT ["/bin/bash", "-c", "/usr/local/bin/import-docker-env.sh && /lib/systemd/systemd"]

这个脚本会把/proc/1/environ里以null分隔的环境变量,转换成export KEY=VALUE的格式写入/etc/profile.d/docker-env.sh——系统中所有用户的登录shell都会自动加载这个目录下的脚本,所以runuser -l root启动的shell就能拿到VNC_PW这些变量了。

方案二:在systemd Unit中直接加载环境变量

如果你不想把变量持久化到文件里(比如担心敏感信息泄露),可以直接在Unit文件的ExecStart里先导入环境变量,再执行脚本:

修改你的Unit文件中的ExecStart行:

ExecStart=/bin/bash -c 'while IFS= read -r -d "" env_var; do export "$env_var"; done < /proc/1/environ; /usr/sbin/runuser -l root -c "/some/script.sh"'

或者更简洁一点(如果你的环境里没有带特殊字符的变量):

ExecStart=/bin/bash -c 'export $(cat /proc/1/environ | tr "\0" "\n") && /usr/sbin/runuser -l root -c "/some/script.sh"'

这种方式的好处是,变量只在脚本执行的上下文里存在,不会被写到磁盘上,安全性更高。

额外补充:为什么runuser -l原来没用?

再理一下原理:systemd启动时会重置环境,只保留少数核心变量(比如PATH、LANG)。runuser -l确实会启动一个登录shell,但这个shell读取的是系统默认的profile配置,这些配置里并没有Docker注入的VNC_PW——除非我们手动把这些变量添加到profile里,或者在执行脚本时直接导入。

内容的提问来源于stack exchange,提问作者Joaquin Morcate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:05:44