我正试着在我的selenium项目中使用我的Docker中的Chrome. 以下是我如何启动Docker

docker run -d -p 4444:4444 -p 7900:7900 --shm-size="2g" selenium/standalone-chrome:latest

然后,在我的代码中,我try 使用RemoteWebDriver连接到我的Docker

val chromeOptions = ChromeOptions()
chromeOptions.addArguments("--no-sandbox")
chromeOptions.addArguments("--headless");
val url = URL("http://localhost:4444/wd/hub")
webDriver = RemoteWebDriver(url, chromeOptions)
val baseUrl = "https://www.google.com"
webDriver.get(baseUrl)
webDriver.quit()

但是,我收到了来自Selify的响应代码500错误.

org.openqa.selenium.SessionNotCreatedException: Could not start a new session. Response code 500. Message: Could not start a new session. Error while creating session with the driver service. Stopping driver service: Could not start a new session. Response code 500. Message: session not created: Chrome failed to start: exited normally.
  (session not created: DevToolsActivePort file doesn't exist)
  (The process started from chrome location /opt/google/chrome/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.) 
Host info: host: 'c3d9edcf7df3', ip: '172.17.0.2'
Build info: version: '4.12.1', revision: '8e34639b11'
System info: os.name: 'Linux', os.arch: 'amd64', os.version: '5.15.49-linuxkit', java.version: '11.0.20.1'
Driver info: driver.version: unknown
Build info: version: '4.12.1', revision: '8e34639b11'
System info: os.name: 'Linux', os.arch: 'amd64', os.version: '5.15.49-linuxkit', java.version: '11.0.20.1'
Driver info: driver.version: unknown
Build info: version: '4.12.1', revision: '8e34639b11'
System info: os.name: 'Mac OS X', os.arch: 'aarch64', os.version: '13.5.1', java.version: '11.0.16.1'
Driver info: org.openqa.selenium.remote.RemoteWebDriver
Command: [null, newSession {capabilities=[Capabilities {browserName: chrome, goog:chromeOptions: {args: [--no-sandbox, --headless], extensions: []}}], desiredCapabilities=Capabilities {browserName: chrome, goog:chromeOptions: {args: [--no-sandbox, --headless], extensions: []}}}]
Capabilities {browserName: chrome, goog:chromeOptions: {args: [--no-sandbox, --headless], extensions: []}}
at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:148)
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:106)
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:67)
        at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:156)
        at org.openqa.selenium.remote.TracedCommandExecutor.execute(TracedCommandExecutor.java:51)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:543)
        at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:229)
        at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:157)
        at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:139)

如何使用Docker for Selify?

我的selenium版本是:

  • selenium-Java :4.8.1
  • selenium chromium 驱动:4.8.1

我还try 升级到最新的Selify版本,即:

  • selenium-Java :4.12.1
  • selenium chromium 驱动:4.12.1

编辑: 将--disable-dev-shm-usage--remote-debugging-port=9222相加后 以下是我的新错误消息

org.openqa.selenium.SessionNotCreatedException: Could not start a new session. Response code 500. Message: Could not start a new session. Error while creating session with the driver service. Stopping driver service: Could not start a new session. Response code 500. Message: session not created: Chrome failed to start: exited normally.
  (chrome not reachable)
  (The process started from chrome location /opt/google/chrome/google-chrome is no longer running, so ChromeDriver is assuming that Chrome has crashed.) 
Host info: host: '419674405ad2', ip: '172.17.0.2'
Build info: version: '4.12.1', revision: '8e34639b11'
System info: os.name: 'Linux', os.arch: 'amd64', os.version: '5.15.49-linuxkit', java.version: '11.0.20.1'
Driver info: driver.version: unknown
Build info: version: '4.12.1', revision: '8e34639b11'
System info: os.name: 'Linux', os.arch: 'amd64', os.version: '5.15.49-linuxkit', java.version: '11.0.20.1'
Driver info: driver.version: unknown
Build info: version: '4.12.1', revision: '8e34639b11'
System info: os.name: 'Mac OS X', os.arch: 'aarch64', os.version: '13.5.1', java.version: '11.0.16.1'
Driver info: org.openqa.selenium.remote.RemoteWebDriver
Command: [null, newSession {capabilities=[Capabilities {browserName: chrome, goog:chromeOptions: {args: [--remote-allow-origins=*, --no-sandbox, --disable-dev-shm-usage, --headless, --disable-extensions, --remote-debugging-port=9222], extensions: []}}]}]
Capabilities {browserName: chrome, goog:chromeOptions: {args: [--remote-allow-origins=*, --no-sandbox, --disable-dev-shm-usage, --headless, --disable-extensions, --remote-debugging-port=9222], extensions: []}}
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:140)
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:96)
        at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:68)
        at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:163)
        at org.openqa.selenium.remote.TracedCommandExecutor.execute(TracedCommandExecutor.java:51)
        at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:602)
        at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:236)
        at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:163)
        at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:143)

推荐答案

我可以连接到localhost:4444,然后正常查看图形用户界面.

After further browsing, seems like the root cause is I'm running it in MacOs m1, which is arm. The current docker image is for amd.
I am trying to find the docker image for the arm now

说得好.

如果基于ARM的映像不可用,您可以try 使用x86_64平台的仿真来运行Docker容器.您可以通过在运行Docker容器时指定--platform flag来完成此操作.

docker run --platform linux/amd64 -d -p 4444:4444 -p 7900:7900 \
           --shm-size="2g" selenium/standalone-chrome:latest

The --platform linux/amd64 flag instructs Docker to emulate the AMD64 (x86_64) architecture on your ARM-based machine. This is particularly useful when you want to run containers that are not yet available for ARM64 architecture.
Docker Desktop for Mac (Apple Silicon) supports this emulation through Apple's Rosetta 2, which allows you to run Intel-based containers on ARM by translating the x86_64 CPU instructions to ARM64.

但是,当然,这种模拟可能会导致性能下降.


the comments中的djmonki所示

That does not work for the selenium provided containers.
It is something to do with the container platform and the fact that selenium are using the intel64 bit chromedriver within the container.

最后,我们转到使用seleniarm docker图像,可以在这里找到:hub.docker.com/u/seleniarm

例如:seleniarm/standalone-docker:用于Selify的多拱形容器镜像,运行在ARM硬件和x86_64上.


最初的答案是:

为了确保Docker容器内部的稳定执行,您可能需要在ChromeOptions的基础上添加一些more arguments.

val chromeOptions = ChromeOptions()
chromeOptions.addArguments("--no-sandbox")
chromeOptions.addArguments("--headless")
chromeOptions.addArguments("--disable-gpu")
chromeOptions.addArguments("--disable-dev-shm-usage")
chromeOptions.addArguments("--remote-debugging-port=9222")
  1. --disable-gpu:禁用GPU硬件加速.这在无头环境中通常很有用.
  2. --disable-dev-shm-usage:该标志将强制Chrome使用磁盘而不是/dev/shm作为共享内存,这可能会解决崩溃问题.
  3. --remote-debugging-port=9222:请参阅Chrome DevTools protocol

注:SessionNotCreatedException通常表示Chrome和ChromeDriver版本不匹配,也可能是因为系统上可用的资源有限.由于您使用的是Docker图像,因此不太可能出现版本不匹配的情况.但是,您可以通过在Docker容器启动时判断日志(log)来验证这一点.

考虑到额外的ChromeOptions和Docker配置,更新后的代码应该如下所示:

val chromeOptions = ChromeOptions()
chromeOptions.addArguments("--no-sandbox")
chromeOptions.addArguments("--headless")
chromeOptions.addArguments("--disable-gpu")
chromeOptions.addArguments("--disable-dev-shm-usage")
chromeOptions.addArguments("--remote-debugging-port=9222")
val url = URL("http://localhost:4444/wd/hub")
webDriver = RemoteWebDriver(url, chromeOptions)
val baseUrl = "https://www.google.com"
webDriver.get(baseUrl)
webDriver.quit()

try 使用这些更改再次运行您的Selify测试.如果问题仍然存在,请判断Docker日志(log)中的Selify容器,以更深入地了解可能导致问题的原因(docker logs <container_id>).

Kotlin相关问答推荐

Kotlin协程挂起继续线程

带有Spring Boot和Kotline的可嵌入实体

解决Microronaut中多个可能的Bean候选者冲突

Kotlin:将泛型添加到列表任何>

Kotlin 函数名后面的大括号是什么意思?

列表在 android WebView 中没有正确迭代

Android Jetpack Compose:在空的 Compose 活动中找不到 OutlinedTextField (Material3)

如何使用 Mockk 模拟返回值类的 Kotlin 函数类型?

如何使用 Kotlin KClass 属性 simpleName 生成空值

.indices 在 kotlin 中的含义是什么?

jetpack compose 将参数传递给 viewModel

Kotlin:如何在活页夹中返回正在运行的服务实例?

如何通过反射使用 Kotlin 对象

片段内的 Kotlin 按钮 onClickListener 事件

Jacoco在Gradle 7.0.2和Kotlin 1.5.10上失败

Kotlin解构when/if语句

指定为非null的参数在ArrayAdaper中为null

可以在函数参数中使用解构吗?

如何将 Kotlin 的 `with` 表达式用于可空类型

如何判断数据是否插入到房间数据库中