如何将Laravel Docker应用切换至测试环境?
问题分析
Laravel默认不会根据APP_ENV自动加载对应后缀的.env文件(比如APP_ENV=testing时自动加载.env.testing),PHPUnit能正常加载是因为phpunit.xml中配置了php/env节点指定了环境文件路径,而Web服务的启动逻辑没有这个处理。硬编码loadEnvironmentFrom('.env.testing')无法实现动态切换,需要调整启动逻辑结合Docker环境变量来实现。
解决方案
1. 修改Laravel启动逻辑,自动匹配环境文件
修改bootstrap/app.php,在创建应用实例前,根据APP_ENV自动加载对应的环境文件:
$app = Illuminate\Foundation\Application::configure(basePath: dirname(__DIR__)) ->loadEnvironmentFrom(".env." . env('APP_ENV', 'local')) // 关键:根据APP_ENV加载对应文件 ->create();
说明:如果
APP_ENV是local,会加载.env.local;如果是testing,加载.env.testing;默认加载.env.local(若不存在会 fallback 到.env)。
2. 通过Docker环境变量动态指定环境
在docker-compose.yml的acme-app服务中添加环境变量,直接设置APP_ENV来匹配对应的.env文件:
services: acme-app: container_name: acme-app build: context: ./devops/php restart: unless-stopped volumes: - ./:/var/www - ./devops/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini environment: - APP_ENV=testing # 设置为testing则加载.env.testing,改为local则加载.env.local networks: - acme-network
3. 容器内临时切换环境
如果需要临时在容器内切换环境,可进入容器后设置环境变量并重启PHP服务:
# 进入PHP容器 docker exec -it acme-app sh # 设置环境变量 export APP_ENV=testing # 重启PHP-FPM(根据容器内服务管理方式调整) php-fpm -t && php-fpm -s reload
注意:这种方式是临时的,容器重启后会恢复原配置,如需持久化需修改
docker-compose.yml。
4. 多端口映射实现多环境并行(可选)
若需要同时运行local和testing环境,可在docker-compose.yml中复制服务配置,分别设置不同环境变量和端口:
services: # Local环境 acme-app-local: container_name: acme-app-local build: context: ./devops/php restart: unless-stopped volumes: - ./:/var/www - ./devops/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini environment: - APP_ENV=local networks: - acme-network acme-server-local: container_name: acme-server-local restart: unless-stopped image: nginx:1.27.0-alpine ports: - 8000:80 volumes: - ./:/var/www - ./devops/nginx/conf.d:/etc/nginx/conf.d/ networks: - acme-network # Testing环境 acme-app-testing: container_name: acme-app-testing build: context: ./devops/php restart: unless-stopped volumes: - ./:/var/www - ./devops/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini environment: - APP_ENV=testing networks: - acme-network acme-server-testing: container_name: acme-server-testing restart: unless-stopped image: nginx:1.27.0-alpine ports: - 8001:80 volumes: - ./:/var/www - ./devops/nginx/conf.d:/etc/nginx/conf.d/ networks: - acme-network
这样可同时通过localhost:8000访问local环境,localhost:8001访问testing环境。
验证
修改完成后重启Docker容器:
docker-compose down && docker-compose up -d
访问对应端口,测试路由会返回对应环境的变量:
- local环境:
APP_ENV=local,DB_CONNECTION=mysql - testing环境:
APP_ENV=testing,DB_CONNECTION=sqlite
内容的提问来源于stack exchange,提问作者João

