GitLab Docker容器运行Laravel Dusk测试报错:9515端口连接被拒
我来帮你排查这个问题——你遇到的Failed to connect to localhost port 9515: Connection refused错误,大概率不是端口被占用,而是Chromedriver根本没在这个端口正常启动,或者Dusk找不到它的运行实例。结合你的Dockerfile和GitLab CI配置,我整理了几个关键修复步骤:
1. 确保Chromedriver与Chrome版本完全匹配
你在Dockerfile里安装了google-chrome-stable,但没有同步安装对应版本的Chromedriver。Dusk默认会尝试自动下载,但容器环境里常因网络、权限问题失败。直接在Dockerfile中添加这段代码,安装和当前Chrome版本兼容的Chromedriver:
# 获取当前Chrome主版本号,下载对应Chromedriver RUN CHROME_VERSION=$(google-chrome-stable --version | sed -r 's/Google Chrome ([0-9]+)\..*/\1/') \ && wget -q https://chromedriver.storage.googleapis.com/LATEST_RELEASE_${CHROME_VERSION} -O /tmp/chromedriver_version \ && wget -q https://chromedriver.storage.googleapis.com/$(cat /tmp/chromedriver_version)/chromedriver_linux64.zip -O /tmp/chromedriver.zip \ && unzip /tmp/chromedriver.zip -d /usr/local/bin/ \ && chmod +x /usr/local/bin/chromedriver \ && rm /tmp/chromedriver.zip /tmp/chromedriver_version
2. 给Dusk配置无头Chrome的必要启动参数
容器环境没有完整的桌面环境,必须让Chrome以无头模式运行,并添加--no-sandbox参数。修改你的DuskTestCase.php中的driver方法:
protected function driver() { $options = (new ChromeOptions)->addArguments([ '--disable-gpu', '--headless', '--no-sandbox', // 容器环境必备参数,否则Chrome无法启动 '--window-size=1920,1080', '--disable-dev-shm-usage', // 解决容器内存不足问题 ]); return RemoteWebDriver::create( 'http://localhost:9515', DesiredCapabilities::chrome()->setCapability( ChromeOptions::CAPABILITY, $options ) ); }
3. 在GitLab CI脚本中启动Xvfb和Chromedriver
你的Dockerfile安装了Xvfb,但没有在CI流程中启动它;同时也没手动启动Chromedriver。更新.gitlab-ci.yml的unit_test阶段脚本:
unit_test: stage: test script: - cp .env.runnable .env - composer install - php artisan config:clear - php artisan key:generate - php artisan migrate --seed - php artisan db:seed --class=TestSeeder - vendor/bin/phpunit --coverage-text --colors=never # 启动虚拟显示服务Xvfb,给Chrome提供运行环境 - Xvfb :99 -ac & - export DISPLAY=:99 # 后台启动Chromedriver,监听9515端口 - chromedriver --url-base=/wd/hub & # 等待Chromedriver完全启动 - sleep 3 - php artisan dusk
4. 额外排查:确认端口监听状态
如果还是报错,可以在CI脚本中加一行检查命令,确认Chromedriver是否真的在9515端口监听:
- netstat -tulpn | grep 9515
如果没有输出,说明Chromedriver启动失败,需要回头检查Chrome与Chromedriver的版本兼容性,或者启动参数是否正确。
补充说明:为什么EXPOSE 9515没用?
你在Dockerfile里添加的EXPOSE 9515其实是多余的——这个指令只是声明容器会使用该端口,并不会自动让服务监听它,也不需要把端口暴露给外部(因为Dusk是在容器内部连接Chromedriver)。真正需要的是确保Chromedriver在容器内部启动并监听9515端口。
按照上面的步骤调整后,应该就能解决连接拒绝的问题了。
内容的提问来源于stack exchange,提问作者Wybren Kortstra

