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

Laravel Sail+Dusk运行测试报错net::ERR_CONNECTION_REFUSED求助

Laravel Sail + Dusk + Selenium 连接拒绝问题排查与解决

问题概述

基于Laravel Sail搭建Docker本地开发环境,环境自带selenium/standalone-chrome容器。安装Dusk后,在sail-8.3/app容器内执行php artisan dusk时触发net::ERR_CONNECTION_REFUSED错误,尝试启动php artisan serve后问题未解决。

报错信息

FAILED  Tests\Browser\HomePageTest > example                                                                    UnknownErrorException   
  unknown error: net::ERR_CONNECTION_REFUSED
  (Session info: chrome=126.0.6478.114)

  at vendor/php-webdriver/webdriver/lib/Exception/WebDriverException.php:146
    142▕                     throw new UnexpectedAlertOpenException($message, $results);
    143▕                 case 'unknown command':
    144▕                     throw new UnknownCommandException($message, $results);
    145▕                 case 'unknown error':
  ➜ 146▕                     throw new UnknownErrorException($message, $results);
    147▕                 case 'unknown method':
    148▕                     throw new UnknownMethodException($message, $results);
    149▕                 case 'unsupported operation':
    150▕                     throw new UnsupportedOperationException($message, $results);

      +5 vendor frames 
  6   tests/Browser/HomePageTest.php:18
  7   tests/Browser/HomePageTest.php:17

相关配置与代码

DuskTestCase.php

abstract class DuskTestCase extends BaseTestCase
{
    /**
     * Prepare for Dusk test execution.
     */
    #[BeforeClass]
    public static function prepare(): void
    {
        if (! static::runningInSail()) {
            static::startChromeDriver();
        }
    }

    /**
     * Create the RemoteWebDriver instance.
     */
    protected function driver(): RemoteWebDriver
    {
        $options = (new ChromeOptions)->addArguments(collect([
            $this->shouldStartMaximized() ? '--start-maximized' : '--window-size=1920,1080',
        ])->unless($this->hasHeadlessDisabled(), function (Collection $items) {
            return $items->merge([
                '--disable-gpu',
                '--headless=new',
            ]);
        })->all());

        return RemoteWebDriver::create(
            $_ENV['DUSK_DRIVER_URL'] ?? 'http://localhost:9515',
            DesiredCapabilities::chrome()->setCapability(
                ChromeOptions::CAPABILITY, $options
            )
        );
    }
}

HomePageTest.php

class HomePageTest extends DuskTestCase
{
    use DatabaseMigrations;
    /**
     * A Dusk test example.
     */
    public function testExample(): void
    {
        $this->browse(function (Browser $browser) {
            $browser->visit('/')
                    ->assertSee('Login');
        });
    }
}

.env配置

已添加:

DUSK_DRIVER_URL=http://selenium:4444

Selenium容器日志

07:43:16.595 INFO [LocalSessionMap.lambda$new$0] - Deleted session from local Session Map, Id: d6234a0ba83b4ac0de1e5c6b70fb616b
07:43:16.595 INFO [GridModel.release] - Releasing slot for session id d6234a0ba83b4ac0de1e5c6b70fb616b
07:43:16.596 INFO [SessionSlot.stop] - Stopping session d6234a0ba83b4ac0de1e5c6b70fb616b
07:43:17.150 INFO [LocalDistributor.newSession] - Session request received by the Distributor: 
 [Capabilities {browserName: chrome, goog:chromeOptions: {args: [--window-size=1920,1080, --disable-gpu, --headless=new]}}]
07:43:17.312 INFO [LocalNode.newSession] - Session created by the Node. Id: 8b9c90b80c4e711d8781e204ab55331f, Caps: Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 126.0.6478.114, chrome: {chromedriverVersion: 126.0.6478.63 (df799988fdc9..., userDataDir: /tmp/.org.chromium.Chromium...}, fedcm:accounts: true, goog:chromeOptions: {debuggerAddress: localhost:45535}, networkConnectionEnabled: false, pageLoadStrategy: normal, platformName: linux, proxy: Proxy(), se:bidiEnabled: false, se:cdp: ws://172.22.0.6:4444/sessio..., se:cdpVersion: 126.0.6478.114, se:vnc: ws://172.22.0.6:4444/sessio..., se:vncEnabled: true, se:vncLocalAddress: ws://172.22.0.6:7900, setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:extension:credBlob: true, webauthn:extension:largeBlob: true, webauthn:extension:minPinLength: true, webauthn:extension:prf: true, webauthn:virtualAuthenticators: true}
07:43:17.315 INFO [LocalDistributor.newSession] - Session created by the Distributor. Id: 8b9c90b80c4e711d8781e204ab55331f 
 Caps: Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 126.0.6478.114, chrome: {chromedriverVersion: 126.0.6478.63 (df799988fdc9..., userDataDir: /tmp/.org.chromium.Chromium...}, fedcm:accounts: true, goog:chromeOptions: {debuggerAddress: localhost:45535}, networkConnectionEnabled: false, pageLoadStrategy: normal, platformName: linux, proxy: Proxy(), se:bidiEnabled: false, se:cdp: ws://172.22.0.6:4444/sessio..., se:cdpVersion: 126.0.6478.114, se:vnc: ws://172.22.0.6:4444/sessio..., se:vncEnabled: true, se:vncLocalAddress: ws://172.22.0.6:7900, setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:extension:credBlob: true, webauthn:extension:largeBlob: true, webauthn:extension:minPinLength: true, webauthn:extension:prf: true, webauthn:virtualAuthenticators: true}
07:43:17.441 WARN [SeleniumSpanExporter$1.lambda$export$3] - {"traceId": "a9a833dc373529e36ebc4b22b4b6b57d","eventTime": 1721893397440430947,"eventName": "HTTP request execution complete","attributes": {"http.flavor": 1,"http.handler_class": "org.openqa.selenium.remote.http.Route$PredicatedRoute","http.host": "selenium:4444","http.method": "POST","http.request_content_length": "35","http.scheme": "HTTP","http.status_code": 500,"http.target": "\u002fsession\u002f8b9c90b80c4e711d8781e204ab55331f\u002furl"}}

07:43:17.869 INFO [LocalSessionMap.lambda$new$0] - Deleted session from local Session Map, Id: 8b9c90b80c4e711d8781e204ab55331f
07:43:17.870 INFO [GridModel.release] - Releasing slot for session id 8b9c90b80c4e711d8781e204ab55331f
07:43:17.872 INFO [SessionSlot.stop] - Stopping session 8b9c90b80c4e711d8781e204ab55331f

排查与解决步骤

1. 明确错误根源

从Selenium日志可以看到,Dusk已经成功与Selenium建立会话(Session created by the Node),所以不是Dusk连不上Selenium,而是运行在Selenium容器内的Chrome浏览器无法访问你的Laravel应用。

Chrome容器内的localhost指向自身,而非app容器,直接访问/会导致连接拒绝。

2. 配置Dusk的基础访问地址

在.env中添加Dusk的基础URL,指定app容器的服务名(Sail默认app容器服务名为app):

DUSK_BASE_URL=http://app:80

或者直接在测试用例中指定完整地址:

public function testExample(): void
{
    $this->browse(function (Browser $browser) {
        $browser->visit('http://app:80/')
                ->assertSee('Login');
    });
}

3. 停止不必要的php artisan serve

Sail的app容器已经通过Nginx监听80端口提供服务,不需要额外启动php artisan serve,这会占用端口并导致冲突。执行以下命令停止该服务(在app容器内):

pkill -f "php artisan serve"

4. 验证容器间网络连通性

  • 在app容器内测试Selenium连通性:
    curl http://selenium:4444
    
    应返回Selenium Grid的页面。
  • 在Selenium容器内测试app连通性:
    docker exec -it <selenium-container-id> curl http://app:80
    
    应返回Laravel应用的页面。

日志警告解析

日志中的HTTP status_code: 500是Selenium处理Chrome访问请求时的内部错误,根源是Chrome无法访问应用地址,解决应用地址配置后该警告会自动消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 10:55:55