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

Docker-Compose环境变量在PHP内置Web服务器中无法读取的问题

问题描述

为复现问题,通过Dockerfile搭建了一个使用PHP内置服务器的Laravel示例应用,Dockerfile内容如下:

FROM composer:latest

WORKDIR /var/www/html

RUN composer create-project laravel/laravel . --no-dev

RUN mv ./.env.example .env

RUN php artisan key:generate

RUN echo "<?php Route::get('test', fn() => dump(getenv('MY_ENV')));" > routes/api.php

CMD php artisan serve --host 0.0.0.0

随后在docker-compose.yml中定义了MY_ENV=123环境变量,配置如下:

version: "3.8"

services: 
  laravel:
    build: .
    tty: true
    ports:
      - '8000:8000'
    environment:
      MY_ENV: 123

执行docker compose up -d启动服务后,访问localhost:8000/api/test,发现getenv('MY_ENV')返回false,但预期值为123。有趣的是,在Laravel Tinker中该变量却可以正常读取。

问题原因
  1. PHP内置服务器的环境变量重置机制:php artisan serve本质是调用PHP内置开发服务器(php -S),该服务器在处理每个HTTP请求时,会重置当前进程的环境变量集合,仅保留CGI规范定义的标准环境变量(如HTTP_HOST、REQUEST_URI等),自定义的MY_ENV会被清除,因此在请求处理流程中用getenv()读取不到。
  2. Tinker与Serve的执行差异:php artisan tinker是直接在启动命令的进程中执行交互逻辑,不会触发内置服务器的环境变量重置操作,因此能正常读取到docker-compose设置的系统环境变量。
  3. Laravel环境变量加载逻辑:Laravel在框架启动阶段会通过Dotenv组件加载所有环境变量(包括系统级和.env文件中的)并缓存到内存中,因此使用Laravel自带的env()助手函数可以读取到值,但getenv()是直接读取当前进程的实时环境变量,受内置服务器的重置影响而失效。
解决办法
  • 替换为Laravel的env()助手函数:将代码中的getenv('MY_ENV')改为env('MY_ENV'),利用Laravel缓存的环境变量数据,不受内置服务器的环境变量重置影响。
  • 避免在开发/生产环境使用php artisan serve:生产环境建议使用Nginx+PHP-FPM的标准部署架构,该架构下环境变量会被完整保留,getenv()可以正常读取。
  • 将环境变量写入.env文件:如果坚持使用getenv(),可以在Dockerfile中添加步骤将环境变量写入.env文件,或者在启动命令中显式传递(但仍需注意内置服务器的限制)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:55:19