Laravel在Docker中执行测试时始终返回local环境问题排查
Docker化Laravel应用测试环境配置问题
问题详情
我有一个Docker化的Laravel应用,其docker-compose.yml内容如下:
version: "3.9" services: app: build: context: ./ dockerfile: Dockerfile image: dmc container_name: dmc-app restart: unless-stopped working_dir: /var/www/ # load development specific .env file env_file: - ./.env.development depends_on: - db - nginx volumes: - ./:/var/www/ - ./docker/php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini - ./docker/php/conf.d/error_reporting.ini:/usr/local/etc/php/conf.d/error_reporting.ini - ./images:/public/images expose: - "9003" networks: - dmc-net nginx: image: nginx:1.23.2-alpine container_name: dmc-nginx restart: unless-stopped ports: - "8000:80" volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d networks: - dmc-net db: image: mysql:8.0.31 container_name: dmc-db restart: unless-stopped ports: - "3307:3306" # use the variables declared in .env file environment: MYSQL_HOST: ${DB_HOST} MYSQL_DATABASE: ${DB_DATABASE} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_ROOT_PASSWORD: abcd1234 MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: development SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d - mysql-data:/var/lib/mysql networks: - dmc-net networks: dmc-net: driver: bridge volumes: mysql-data:
执行测试命令:
docker-compose exec app ./vendor/bin/pest tests/Feature/ReturnsTest.php
测试过程中应用使用本地MySQL数据库而非SQLite,在测试中加入dd(App::environment());验证,结果返回local而非预期的testing。
未修改过phpunit.xml文件,确认其存在于容器中,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true" > <testsuites> <testsuite name="Unit"> <directory suffix="Test.php">./tests/Unit</directory> </testsuite> <testsuite name="Feature"> <directory suffix="Test.php">./tests/Feature</directory> </testsuite> </testsuites> <coverage processUncoveredFiles="true"> <include> <directory suffix=".php">./app</directory> </include> </coverage> <php> <env name="APP_ENV" value="testing"/> <env name="BCRYPT_ROUNDS" value="4"/> <env name="CACHE_DRIVER" value="array"/> <env name="DB_CONNECTION" value="sqlite"/> <env name="DB_DATABASE" value=":memory:"/> <env name="MAIL_MAILER" value="array"/> <env name="QUEUE_CONNECTION" value="sync"/> <env name="SESSION_DRIVER" value="array"/> <env name="TELESCOPE_ENABLED" value="false"/> </php> </phpunit>
按网上建议创建了.env.testing文件,内容如下,但未解决问题:
APP_ENV=testing DB_CONNECTION=sqlite DB_DATABASE=:memory:
更新1:docker-compose exec app php artisan about的输出:
docker-compose exec app php artisan about ✔ 8s Xdebug: [Step Debug] Could not connect to debugging client. Tried: host.docker.internal:9003 (through xdebug.client_host/xdebug.client_port). Environment ............................................................................................... Application Name ......................................................................... DunderMifflin-be Laravel Version .................................................................................... 9.40.1 PHP Version ........................................................................................ 8.1.12 Composer Version .................................................................................... 2.8.4 Environment ......................................................................................... local Debug Mode ........................................................................................ ENABLED URL ............................................................................................. localhost Maintenance Mode ...................................................................................... OFF Cache ..................................................................................................... Config ......................................................................................... NOT CACHED Events ......................................................................................... NOT CACHED Routes ......................................................................................... NOT CACHED Views .............................................................................................. CACHED Drivers ................................................................................................... Broadcasting .......................................................................................... log Cache ................................................................................................ file Database ............................................................................................ mysql Logs .................................................... stack / debug, info, warning, critical, emergency Mail ................................................................................................. smtp Queue ............................................................................................ database Session .............................................................................................. file
问题原因
Laravel环境变量的优先级为:系统环境变量 > .env文件 > phpunit.xml中的app服务通过env_file加载了.env.development,其中的APP_ENV=local会作为系统环境变量注入容器,优先级高于phpunit.xml和.env.testing的配置,导致测试时Laravel识别的环境是local,进而使用MySQL数据库。
解决办法
方法1:执行测试时显式指定环境变量
在执行测试命令时直接覆盖APP_ENV:
docker-compose exec app APP_ENV=testing ./vendor/bin/pest tests/Feature/ReturnsTest.php
方法2:创建测试专用的Docker Compose配置
新建docker-compose.test.yml:
version: "3.9" services: app: env_file: - ./.env.testing environment: - APP_ENV=testing
执行测试时加载该配置:
docker-compose -f docker-compose.yml -f docker-compose.test.yml exec app ./vendor/bin/pest tests/Feature/ReturnsTest.php
方法3:清除配置缓存
如果之前缓存过配置,先执行清除命令:
docker-compose exec app php artisan config:clear
确保测试时Laravel读取最新的环境变量配置。
内容的提问来源于stack exchange,提问作者MrCujo
相关产品推荐
相关产品推荐

