django-environ无法读取Docker容器环境变量问题排查
问题根因
django-environ的Env实例不会默认自动同步当前进程os.environ里存的系统环境变量,它只会查询你主动给它加载的变量源:要么是显式调用方法读取的本地.env文件,要么是初始化实例时手动传进去的变量字典,不会自己主动去读os.environ里的内容。
你的场景里,环境变量是docker-compose通过env_file配置直接注入到容器系统环境表的,echo $SECRET_KEY和os.environ.get('SECRET_KEY')能拿到值,是因为这俩都是直接读系统环境表。但你的代码没给Env实例加载这些系统环境变量,实例内部的变量池是空的,自然读不到SECRET_KEY;报错里显示default为<NoValue>是老版本django-environ的逻辑bug,没加载到变量源的时候不会正确识别你传入的默认值参数。
修复方法
选任意一种调整settings里的初始化逻辑就行:
方案1:显式调用read_env()同步环境变量
这是官方推荐的兼容写法,read_env()方法默认会先把当前os.environ里的所有变量同步到Env实例,再尝试读取本地.env文件的内容,容器环境下就算项目里没有.env文件也不会报错:
import environ env = environ.Env() # 加这一行就行,主动把系统环境变量加载到Env实例 env.read_env() SECRET_KEY = env('SECRET_KEY', default='some_other_value')
如果担心生产环境误读项目目录里残留的本地开发用.env文件,可以给read_env()传空路径跳过本地文件读取,只加载系统注入的变量:
import os import environ env = environ.Env() # 跳过本地.env文件读取,仅加载系统环境变量 env.read_env(env_file=os.devnull) SECRET_KEY = env('SECRET_KEY', default='some_other_value')
方案2:初始化时直接传入系统环境变量
初始化Env实例的时候直接把os.environ解包传进去,一步到位加载所有系统环境变量:
import os import environ # 初始化时直接加载所有系统环境变量 env = environ.Env(**os.environ) SECRET_KEY = env('SECRET_KEY', default='some_other_value')
补充说明
- 很多本地开发教程里没强调要加
read_env()也能跑,是因为本地开发时通常会显式传本地.env文件路径给read_env(),调用这个方法的时候顺便就把os.environ里的变量同步进去了,容器场景下没有读本地文件的步骤,就会踩这个坑。 - 把django-environ升级到最新稳定版,也能修复老版本里没加载到变量源时默认值不生效的问题。
内容的提问来源于stack exchange,提问作者Eduardo Gomes
相关产品推荐
相关产品推荐

