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

Docker容器启动脚本设置全局环境变量不生效问题

问题根因

你遇到的现象和脚本写法对错无关,本质是Linux环境变量的固有继承规则:

  • 环境变量只能由父进程在fork子进程时单向传递给子进程,子进程启动后会持有一份环境变量的独立拷贝,后续修改变量既不会影响父进程,也不会影响同层级无亲缘关系的其他进程。不存在所谓“动态修改后所有进程全局可见”的运行时环境变量机制。
  • 你当前的entrypoint脚本逻辑本身是生效的:export FQDN之后通过exec "$@"启动的apache2-foreground主进程,以及apache后续fork出的所有PHP工作进程、CGI进程,全都是entrypoint bash进程的子进程,这些业务进程本身是可以正常读到FQDN变量的。
  • 你通过docker exec进入容器执行env看不到变量,是因为docker exec启动的shell进程是Docker守护进程直接在容器内拉起的独立进程,不属于apache进程的子进程树,只会加载容器启动时的初始静态环境,自然拿不到entrypoint运行时动态生成的变量。
  • 你之前测试docker run --rm [镜像名:tag] env能看到FQDN,是因为此时传入的CMD是env命令,它是entrypoint脚本exec拉起的子进程,符合继承规则,所以能读到值。
  • 你尝试的source执行方式也不可能实现“全局所有进程可见”:手动在登录shell里source脚本时,变量仅对当前shell和它启动的子进程生效,新开一个终端会话一样读不到,和容器场景的逻辑完全一致。
落地方案

根据你的实际需求分两种情况配置:

仅需业务进程(Apache/MediaWiki)读取变量

你现有的脚本已经满足需求,不需要额外修改。可以直接在容器内执行以下命令验证apache进程确实拿到了变量:

cat /proc/$(pidof apache2 | awk '{print $1}')/environ | tr '\0' '\n' | grep FQDN

PHP代码中通过getenv('FQDN')即可正常读取到公网IP值。
小优化:给curl加上-s参数关闭进度条输出,避免无用日志:

export FQDN=$(curl -s checkip.amazonaws.com)

注意:你当前的Dockerfile直接覆盖了mediawiki基础镜像的原生ENTRYPOINT,官方镜像默认的ENTRYPOINT会做目录权限初始化、配置文件自动生成等前置操作,直接覆盖可能出现www-data用户无文件权限、配置不生效的问题,建议将自定义脚本逻辑追加到原生ENTRYPOINT逻辑前执行,不要直接覆盖。

需要docker exec进入容器的交互shell也能读取变量

如果需要手动进容器调试时也能直接读到FQDN变量,在现有startup.sh中追加逻辑,将变量写入系统全局shell加载配置即可,所有新启动的登录/交互shell都会自动加载该变量:

#!/bin/bash
# 获取公网IP
export FQDN=$(curl -s checkip.amazonaws.com)
echo $FQDN

# 写入全局shell配置,所有新开的bash进程自动加载
echo "export FQDN=${FQDN}" >> /etc/profile
echo "export FQDN=${FQDN}" >> /etc/bash.bashrc
# 写入系统全局环境文件,兼容非bash类进程读取
echo "FQDN=${FQDN}" >> /etc/environment

exec "$@"

配置完成后,无论是Apache业务进程,还是后续exec进入容器的命令行进程,都可以正常读取到FQDN变量值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:33:23