Docker运行JS版Selenium测试报ERR_CONNECTION_REFUSED错误
问题场景
在Docker中运行JavaScript编写的Selenium测试时抛出连接拒绝异常,相同测试逻辑的Java版本可在同一Docker环境正常运行。
测试代码如下:
const { Builder, By} = require("selenium-webdriver"); const chrome = require('selenium-webdriver/chrome'); const assert = require('assert') async function addCadastreTest() { const options = new chrome.Options() options.setAcceptInsecureCerts(true) let driver = await new Builder() .forBrowser("chrome") .usingServer('http://localhost:4444/wd/hub') .setChromeOptions(options) .build(); await driver.get("http://localhost:3000/"); await driver.findElement(By.id("fit")).click() assert(await driver.switchTo().alert().getText() == "Quel est le nom de votre commune ?") { const alert = await driver.switchTo().alert() await alert.sendKeys("Lons le Saunier") await alert.accept() } await driver.quit(); } addCadastreTest();
报错栈信息:
mapbox\node_modules\selenium-webdriver\lib\error.js:522 let err = new ctor(data.message) ^ WebDriverError: unknown error: net::ERR_CONNECTION_REFUSED (Session info: chrome=102.0.5005.61) at Object.throwDecodedError mapbox\node_modules\selenium-webdriver\lib\error.js:522:15) at parseHttpResponse (mapbox\node_modules\selenium-webdriver\lib\http.js:549:13) at Executor.execute (mapbox\node_modules\selenium-webdriver\lib\http.js:475:28) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async Object.execute (mapbox\node_modules\selenium-webdriver\lib\webdriver.js:735:17) at async addCadastreTest (mapbox\test\addCadastre.spec.js:14:5) { remoteStacktrace:
根因分析
- 报错本质是Selenium容器内的Chrome浏览器无法访问目标前端服务,和Selenium Server本身连接无关:代码中
driver.get("http://localhost:3000/")里的localhost指向的是Chrome运行所在的Selenium容器自身的回环地址,既不是宿主机地址,也不是运行测试脚本的环境地址,Selenium容器内部的3000端口并没有运行前端服务,自然触发连接拒绝错误。 - Java版本可正常运行,是因为Java代码中配置的前端服务地址没有用localhost,要么配置了Docker网络内的服务域名、要么用了正确的宿主机地址,和编程语言本身没有关系。
修复方案
- 第一步:将Selenium容器、前端服务容器、测试脚本执行容器都加入同一个自定义Docker网络,不要使用默认桥接网络,保证容器间可通过容器名互相访问。
- 第二步:修改测试代码中访问前端的地址,禁止使用localhost:
- 如果使用自定义Docker网络,直接把地址替换为前端服务的容器名即可,比如前端容器名为
web-app,对应访问地址写http://web-app:3000,Docker内置DNS会自动完成地址解析。 - 如果前端服务直接跑在宿主机、没有做容器化,Windows/Mac环境下用Docker Desktop提供的默认域名
host.docker.internal替换localhost,即写http://host.docker.internal:3000;Linux环境可以用Docker默认网桥网关地址172.17.0.1替换localhost,或者启动容器时添加--add-host=host.docker.internal:host-gateway参数后,和Mac/Windows环境一样用host.docker.internal访问宿主机服务。
- 如果使用自定义Docker网络,直接把地址替换为前端服务的容器名即可,比如前端容器名为
- 验证:跑测试前可以进入Selenium容器内部,用curl命令直接访问修改后的前端地址,确认连通性正常后再执行测试即可。
内容的提问来源于stack exchange,提问作者Twistere
相关产品推荐
相关产品推荐

