我正在使用 Firefox 和 Geckodriver 在 docker 容器内运行 selenium 测试。以 root 身份运行该容器时,一切正常。
以非 root 用户(USER 1000)运行容器时,驱动程序初始化失败:
[[1;31mERROR[m] test01_WO_default_dashboard Time elapsed: 132.6 s <<< ERROR!
org.openqa.selenium.TimeoutException:
Failed to read marionette port
Build info: version: '3.14.0', revision: 'aacccce0', time: '2018-08-02T20:19:58.91Z'
System info: host: 'testrunner-cockpit-3--1-mdbwj', ip: '10.130.2.18', os.name: 'Linux', os.arch: 'amd64', os.version: '4.18.0-305.28.1.el8_4.x86_64', java.version: '11.0.15'
Driver info: driver.version: FirefoxDriver
remote stacktrace:
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.openqa.selenium.remote.W3CHandshakeResponse.lambda$new$0(W3CHandshakeResponse.java:57)
at org.openqa.selenium.remote.W3CHandshakeResponse.lambda$getResponseFunction$2(W3CHandshakeResponse.java:104)
at org.openqa.selenium.remote.ProtocolHandshake.lambda$createSession$0(ProtocolHandshake.java:122)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:958)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:543)
at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:125)
at org.openqa.selenium.remote.ProtocolHandshake.createSession(ProtocolHandshake.java:73)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:136)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:548)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:212)
at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:130)
at org.openqa.selenium.firefox.FirefoxDriver.<init>(FirefoxDriver.java:125)
我的 Dockerfile 的相关部分:
FROM ubuntu:20.04
# install firefox
ARG FIREFOX_VERSION=latest
RUN FIREFOX_DOWNLOAD_URL=$(if [ $FIREFOX_VERSION = "latest" ] || [ $FIREFOX_VERSION = "nightly-latest" ] || [ $FIREFOX_VERSION = "devedition-latest" ] || [ $FIREFOX_VERSION = "esr-latest" ]; then echo "https://download.mozilla.org/?product=firefox-$FIREFOX_VERSION-ssl&os=linux64&lang=en-US"; else echo "https://download-installer.cdn.mozilla.net/pub/firefox/releases/$FIREFOX_VERSION/linux-x86_64/en-US/firefox-$FIREFOX_VERSION.tar.bz2"; fi) \
&& apt-get update -qqy \
&& apt-get -qqy --no-install-recommends install firefox libavcodec-extra \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/* \
&& wget --no-verbose -O /tmp/firefox.tar.bz2 $FIREFOX_DOWNLOAD_URL \
&& apt-get -y purge firefox \
&& rm -rf /opt/firefox \
&& tar -C /opt -xjf /tmp/firefox.tar.bz2 \
&& rm /tmp/firefox.tar.bz2 \
&& mv /opt/firefox /opt/firefox-$FIREFOX_VERSION \
&& ln -fs /opt/firefox-$FIREFOX_VERSION/firefox /usr/bin/firefox
# install geckodriver
ARG GECKODRIVER_VERSION=latest
RUN GK_VERSION=$(if [ ${GECKODRIVER_VERSION:-latest} = "latest" ]; then echo "0.31.0"; else echo $GECKODRIVER_VERSION; fi) \
&& echo "Using GeckoDriver version: "$GK_VERSION \
&& wget --no-verbose -O /tmp/geckodriver.tar.gz https://github.com/mozilla/geckodriver/releases/download/v$GK_VERSION/geckodriver-v$GK_VERSION-linux64.tar.gz \
&& rm -rf /opt/geckodriver \
&& tar -C /opt -zxf /tmp/geckodriver.tar.gz \
&& rm /tmp/geckodriver.tar.gz \
&& mv /opt/geckodriver /opt/geckodriver-$GK_VERSION \
&& chmod 755 /opt/geckodriver-$GK_VERSION \
&& ln -fs /opt/geckodriver-$GK_VERSION /usr/bin/geckodriver \
&& geckodriver --version
我甚至添加了一些 chmod / chown 来尝试修复 firefox 或 geckodriver 的一些权限问题:
RUN chown 1000 -R /usr/bin/geckodriver \
&& chmod 775 -R /usr/bin/geckodriver \
&& chown 1000 -R /usr/bin/firefox \
&& chmod 775 -R /usr/bin/firefox
最后是 USER 指令,以非 root 身份运行容器
USER 1000
我没有手动安装 selenium。它是我正在安装的项目的 maven 依赖项,我的测试源位于该项目中。
答案1
我在尝试在 Kubernetes 上的 Docker 容器内启动无头 Firefox 时遇到了同样的问题。我解决这个问题的方法是将下面的代码添加到我的Dockerfile
RUN groupadd ffgroup --gid 2000 \
&& useradd ffuser \
--create-home \
--home-dir /tmp/ffuser \
--gid 2000 \
--shell /bin/bash \
--uid 1000
然后将以下内容添加到容器的规范中:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 2000
fsGroup: 2000