结论:.env.prod 文件本身不应该存在或被使用——它不是 Symfony 官方支持的加载目标;正确做法是使用 .env.prod.local(需确保 APP_ENV=prod 已由系统级环境变量预设、该文件在 .gitignore 中且语法无误),并在线上通过 dotenv:dump 生成 .env.local.php 以避免运行时解析开销。

直接说结论:.env.prod 文件本身**不应该存在或被使用**——它不是 Symfony 官方支持的加载目标,硬建这个文件只会让你掉进环境加载顺序和部署安全的坑里。
为什么 .env.prod 不该手动创建
Symfony 的 Dotenv 加载顺序是固定的:.env → .env.local → .env.$APP_ENV → .env.$APP_ENV.local。注意:只有当 APP_ENV=prod 已被系统级设置(如 Web 服务器配置或 shell 环境)时,.env.prod 才会被读取;否则它完全被忽略。
- 常见错误现象:
.env.prod写好了,但bin/console debug:container --env-var=DATABASE_URL仍显示空值 - 根本原因:CLI 或 Web 服务器没真正设好
APP_ENV=prod,loadEnv()根本不触发对.env.prod的查找 - 更严重的问题:
.env.prod很容易误提交到 Git,把生产密钥暴露出去——它不像.env.prod.local那样被官方文档明确列为“应进.gitignore”的文件
.env.prod.local 才是正确写法
你要配的是 .env.prod.local,且必须满足三个前提:
-
APP_ENV=prod已通过 Web 服务器(Nginxfastcgi_param/ ApacheSetEnv)或系统级export设置,而不是靠.env里写APP_ENV=prod -
.env.prod.local必须在项目根目录,且已加入.gitignore(检查git status是否显示为未跟踪) - 语法必须干净:不能有未闭合的
${}、漏引号、中文冒号等,否则Dotenv解析失败且静默跳过
示例内容(注意引号和换行):
DATABASE_URL="mysql://user:%env(resolve:DB_PASSWORD)%@db:3306/app?charset=utf8mb4" DB_PASSWORD="myrealprodpass" REDIS_URL="redis://cache:6379"
生产环境别依赖 .env.* 实时解析
即使 .env.prod.local 能加载,线上也不该让它参与每次请求——Dotenv 解析有性能开销,且 Web 服务器启动后 loadEnv() 可能已关闭。
- 正确做法:本地构建阶段运行
php bin/console dotenv:dump --format=php --env=prod,生成.env.local.php - 部署时只传
.env.local.php,删掉所有.env.*文本文件 - 此时
APP_ENV=prod命令可直接运行,变量从 PHP 数组中秒级读取,无解析成本
验证是否真生效的三件事
别只看文件是否存在,要确认运行时状态:
- CLI 下执行
echo $APP_ENV,输出必须是prod(不是空、不是dev) - 运行
php bin/console debug:dotenv --env=prod,看输出里是否列出你定义的变量(如DB_PASSWORD),且状态为loaded - 查缓存:执行
php bin/console cache:clear --env=prod后,再看var/cache/prod/srcApp_KernelProdContainer.php中相关参数是否已被替换为真实值
最易被忽略的一点:改完 .env.prod.local 后,cache:clear 必须带 --env=prod 参数,否则它清的是 dev 缓存,变量还是旧的。


















