Selenium集成Docker与Azure Pipeline时遇SessionNotCreated错误求助
问题描述
在将Selenium与Docker及Azure Pipeline集成时,出现无法创建新会话的错误,错误信息:
SessionNotCreated could not start a new session. possible causes are invalid address of the remote server or browser start-up failure
错误日志
Command: [null, newSession {capabilities=[Capabilities {acceptInsecureCerts: true, browserName: chrome, goog:chromeOptions: {args: [--disable-notifications], extensions: []}}]}] Capabilities {acceptInsecureCerts: true, browserName: chrome, goog:chromeOptions: {args: [--disable-notifications], extensions: []}} [ERROR] SampleRun.setup:68 » SessionNotCreated Could not start a new session. Possible causes are invalid address of the remote server or browser start-up failure. Host info: host: 'fv-az369-95', ip: '10.1.0.4' Build info: version: '4.19.1', revision: 'abe0ee07dc' System info: os.name: 'Linux', os.arch: 'amd64', os.version: '6.5.0-1018-azure', java.version: '11.0.22' Driver info: org.openqa.selenium.remote.RemoteWebDriver Command: [null, newSession {capabilities=[Capabilities {acceptInsecureCerts: true, browserName: MicrosoftEdge, ms:edgeOptions: {args: [], extensions: []}}]}] Capabilities {acceptInsecureCerts: true, browserName: MicrosoftEdge, ms:edgeOptions: {args: [], extensions: []}} [INFO] [ERROR] Tests run: 6, Failures: 2, Errors: 0, Skipped: 4 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 47.179 s [INFO] Finished at: 2024-04-25T02:15:53Z [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.2.5:test (default-test) on project DTest: There are test failures. [ERROR] [ERROR] Please refer to /home/vsts/work/1/s/target/surefire-reports for the individual test results. [ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream. [ERROR] -> [Help 1] [ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch. [ERROR] Re-run Maven using the -X switch to enable full debug logging. [ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles: [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException ##[debug]Exit code 1 received from tool '/usr/bin/bash' ##[debug]STDIO streams have closed for tool '/usr/bin/bash' ##[error]Bash exited with code '1'. ##[debug]Processed: ##vso[task.issue type=error;source=TaskInternal;]Bash exited with code '1'. ##[debug]task result: Failed ##[debug]Processed: ##vso[task.complete result=Failed;done=true;] Finishing: Maven clean install
Azure-pipeline.yml原配置
trigger: - main pool: vmImage: 'ubuntu-latest' variables: java.version: '16' jobs: - job: 'Setup' displayName: 'Setup Environment' steps: - script: | sudo apt-get update sudo apt-get install -y openjdk-$(java.version)-jdk echo "Java version:" java -version displayName: 'Set up Java' - script: | sudo apt-get remove containerd displayName: 'Remove conflicting packages' - script: | sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io displayName: 'Install Docker from official repository' - script: | sudo apt-get update sudo apt-get install -y maven mvn -version displayName: 'Install Maven' - script: | sudo apt-get update sudo apt-get install -y unzip wget https://selenium-release.storage.googleapis.com/4.18/selenium-java-4.18.1.zip unzip selenium-java-4.18.1.zip -d selenium-java cp selenium-java/libs/* . rm -rf selenium-java selenium-java-4.18.1.zip displayName: 'Install Selenium Java dependencies' - job: 'Docker' displayName: 'Run Docker Containers' dependsOn: Setup steps: - script: | docker run -d -p 4442:4442 -p 4443:4443 --shm-size=2g \ -e SE_EVENT_BUS_HOST=selenium-hub \ -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ -e VNC_NO_PASSWORD=1 \ -e SE_NODE_MAX_SESSIONS=2 \ --name chrome selenium/node-chrome:4.18.1-20240224 displayName: 'Run Chrome Node Docker container' - script: | docker run -d -p 4444:4444 -p 4445:4445 --shm-size=2g \ -e SE_EVENT_BUS_HOST=selenium-hub \ -e SE_EVENT_BUS_PUBLISH_PORT=4444 \ -e SE_EVENT_BUS_SUBSCRIBE_PORT=4445 \ -e VNC_NO_PASSWORD=1 \ -e SE_NODE_MAX_SESSIONS=2 \ --name edge selenium/node-edge:4.18.1-20240224 displayName: 'Run Edge Node Docker container' - script: | docker run -d -p 4446:4446 -p 4447:4447 -p 4448:4448 \ --name selenium-hub selenium/hub:4.18.1-20240224 displayName: 'Run Selenium Hub Docker container' - job: 'Tests' displayName: 'Run Tests' dependsOn: Docker steps: - script: | mvn clean install displayName: 'Maven clean install' - script: | mvn test displayName: 'Run Selenium tests'
核心Selenium测试代码
public class SampleRun { private static ThreadLocal<WebDriver> driverThreadLocal = new ThreadLocal<>(); public WebDriver getDriver() { return driverThreadLocal.get(); } public void setDriver(WebDriver driver) { driverThreadLocal.set(driver); } public void quitDriver() { WebDriver driver = driverThreadLocal.get(); if (driver != null) { driver.quit(); driverThreadLocal.remove(); } } @BeforeTest @Parameters({ "browser" }) public void setup(String browser) throws MalformedURLException { URL hubUrl = new URL("http://localhost:4444/wd/hub"); switch (browser.toLowerCase()) { case "chrome": ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.addArguments("--disable-notifications"); // Disable browser notifications chromeOptions.setAcceptInsecureCerts(true); // Accept insecure certificates setDriver(new RemoteWebDriver(hubUrl, chromeOptions)); break; case "edge": EdgeOptions edgeOptions = new EdgeOptions(); edgeOptions.setAcceptInsecureCerts(true); setDriver(new RemoteWebDriver(hubUrl, edgeOptions)); break; default: throw new IllegalArgumentException("Invalid browser: " + browser); } if (getDriver() == null) { throw new IllegalStateException("WebDriver is not initialized properly."); } System.out.println("WebDriver initialized for " + browser); } @Test public void testScenario1() throws InterruptedException { getDriver().get("https://www.google.com"); Thread.sleep(2000); System.out.println("Page title: " + getDriver().getTitle()); } @Test public void testScenario2() throws InterruptedException { getDriver().get("https://www.facebook.com"); Thread.sleep(2000); System.out.println("Page title: " + getDriver().getTitle()); } @Test public void testScenario3() throws InterruptedException { getDriver().get("https://www.reddit.com"); Thread.sleep(2000); System.out.println("Page title: " + getDriver().getTitle()); } @AfterTest public void teardown() { quitDriver(); } }
问题排查与修改方案
1. 核心问题:Azure Pipeline多Job环境隔离
Azure Pipeline中每个Job都会在独立的虚拟机上执行,Setup、Docker、Tests三个Job属于不同的执行环境,Tests Job无法访问Docker Job中启动的容器。必须将所有步骤合并到同一个Job中。
2. Docker容器配置错误
2.1 容器启动顺序错误
必须先启动Selenium Hub,再启动浏览器Node,否则Node无法连接到Hub。
2.2 Hub端口映射不匹配
测试代码中连接的是localhost:4444,但原配置中Hub的端口映射是4446:4446,需要改成4444:4444。
2.3 Node连接Hub的环境变量错误
Selenium Grid 4中,Node连接Hub应使用SE_HUB_HOST和SE_HUB_PORT环境变量,而非SE_EVENT_BUS_*(该变量用于分布式事件总线场景)。
2.4 容器网络隔离
默认Docker网络下,容器间无法通过名称互相访问,需创建自定义网络,将Hub和Node加入同一网络。
2.5 Selenium版本不匹配
测试代码使用Selenium 4.19.1,而Docker镜像使用4.18.1,版本不一致会导致兼容性问题,需统一版本。
3. 修改后的Azure-pipeline.yml
trigger: - main pool: vmImage: 'ubuntu-latest' variables: java.version: '16' selenium.version: '4.19.1' selenium.hub.image: 'selenium/hub:$(selenium.version)-20240423' chrome.node.image: 'selenium/node-chrome:$(selenium.version)-20240423' edge.node.image: 'selenium/node-edge:$(selenium.version)-20240423' jobs: - job: 'RunTests' displayName: 'Setup, Run Docker and Tests' steps: - script: | sudo apt-get update sudo apt-get install -y openjdk-$(java.version)-jdk echo "Java version:" java -version displayName: 'Set up Java' - script: | sudo apt-get remove containerd displayName: 'Remove conflicting packages' - script: | sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io displayName: 'Install Docker from official repository' - script: | sudo apt-get update sudo apt-get install -y maven mvn -version displayName: 'Install Maven' - script: | sudo apt-get update sudo apt-get install -y unzip wget https://selenium-release.storage.googleapis.com/$(selenium.version.split('.')[0]).$(selenium.version.split('.')[1])/selenium-java-$(selenium.version).zip unzip selenium-java-$(selenium.version).zip -d selenium-java cp selenium-java/libs/* . rm -rf selenium-java selenium-java-$(selenium.version).zip displayName: 'Install Selenium Java dependencies' - script: | docker network create selenium-grid-network displayName: 'Create Selenium Grid Docker Network' - script: | docker run -d -p 4444:4444 -p 4442:4442 -p 4443:4443 \ --network selenium-grid-network \ --name selenium-hub $(selenium.hub.image) displayName: 'Run Selenium Hub Docker container' - script: | docker run -d --shm-size=2g \ --network selenium-grid-network \ -e SE_HUB_HOST=selenium-hub \ -e SE_HUB_PORT=4444 \ -e VNC_NO_PASSWORD=1 \ -e SE_NODE_MAX_SESSIONS=2 \ --name chrome $(chrome.node.image) displayName: 'Run Chrome Node Docker container' - script: | docker run -d --shm-size=2g \ --network selenium-grid-network \ -e SE_HUB_HOST=selenium-hub \ -e SE_HUB_PORT=4444 \ -e VNC_NO_PASSWORD=1 \ -e SE_NODE_MAX_SESSIONS=2 \ --name edge $(edge.node.image) displayName: 'Run Edge Node Docker container' - script: | # 等待Hub和Node启动完成 echo "Waiting for Selenium Grid to be ready..." while ! curl -s http://localhost:4444/status | grep -q "ready"; do sleep 5 done echo "Selenium Grid is ready" displayName: 'Wait for Selenium Grid to Initialize' - script: | mvn clean install displayName: 'Maven clean install' - script: | mvn test displayName: 'Run Selenium tests' - script: | # 清理容器和网络 docker stop selenium-hub chrome edge docker rm selenium-hub chrome edge docker network rm selenium-grid-network displayName: 'Clean Up Docker Resources'
4. 测试代码调整(可选)
确保pom.xml中的Selenium版本与Docker镜像版本一致(4.19.1),避免手动下载Selenium依赖,直接通过Maven管理更可靠:
<dependencies> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.19.1</version> </dependency> <!-- 添加其他测试依赖如TestNG等 --> </dependencies>
5. 额外优化点
- 移除手动下载Selenium依赖的步骤,通过Maven自动管理依赖,避免版本不一致和文件复制问题。
- 添加等待Selenium Grid就绪的步骤,确保Hub和Node完全启动后再运行测试。
- 添加Docker资源清理步骤,避免环境残留。
内容的提问来源于stack exchange,提问作者Maxx muthu

