在 Docker 容器中以非 root 用户身份运行 Selenium + geckodriver + firefox 时“无法读取 marionette 端口”

问题描述 投票:0回答:7

我正在 Docker 容器内使用 Firefox 和 Geckodriver 运行 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

最后是以非 root 身份运行容器的 USER 指令

USER 1000

我不手动安装selenium。这是我正在安装的测试源所在的项目的 Maven 依赖项。

docker selenium firefox geckodriver
7个回答
4
投票

你也可以通过apt安装firefox,这一步为我解决了这个问题。 (https://github.com/FortyNorthSecurity/EyeWitness/issues/604https://www.omgubuntu.co.uk/2022/04/how-to-install-firefox-deb-apt-ubuntu- 22-04)

第 1 步:通过在新的终端窗口中运行以下命令来删除 Firefox Snap:

sudo snap remove firefox

第 2 步:通过在同一终端窗口中运行以下命令,将 (Ubuntu) Mozilla 团队 PPA 添加到您的软件源列表中:

sudo add-apt-repository ppa:mozillateam/ppa

第 3 步:接下来,更改 Firefox 软件包优先级,以确保首选 PPA/deb/apt 版本的 Firefox。这可以使用 FosTips 中的一段代码来完成(整个复制并粘贴,而不是逐行粘贴):

echo '
Package: *
Pin: release o=LP-PPA-mozillateam
Pin-Priority: 1001
' | sudo tee /etc/apt/preferences.d/mozilla-firefox

第 4 步:由于您(希望)希望自动安装未来的 Firefox 升级,Balint Reczey 在他的博客上分享了一个简洁的命令,以确保它发生:

echo 'Unattended-Upgrade::Allowed-Origins:: "LP-PPA-mozillateam:${distro_codename}";' | sudo tee /etc/apt/apt.conf.d/51unattended-upgrades-firefox

第 5 步:最后,运行以下命令通过 apt 安装 Firefox:

sudo apt install firefox

2
投票

我最近遇到了同样的问题,并尝试通过以下方式解决它

  1. 在 Dockerfile 中创建一个目录
    /.cache
mkdir -p /.cache;\

并给予

/.cache
目录写权限

chmod 777 /.cache;\
  1. 如果您使用指定的用户 ID(即 Jenkins id)运行 docker,那么您需要在
    yourcontainername:/etc/passwd
  2. 中添加一些带有 userid 和 groupid 的用户名
echo "somename:x:1234:1235:somename:/tmp:/bin/bash" >> /tmp/passwd 

下面是我安装geckodriver的Dockerfile,复制到这里供大家参考,希望对您有帮助! #########################################

RUN (install_dir="/opt/automation/data/webdriver"; \
    url=$(curl -s https://api.github.com/repos/mozilla/geckodriver/releases/latest | python -c "import sys, json; print(next(item['browser_download_url'] for item in json.load(sys.stdin)['assets'] if 'linux64' in item.get('browser_download_url', '')))"); \
    echo "url  $url"; \
    wget  -O geckodriver.tar.gz "$url"; \
    tar -xvzf geckodriver.tar.gz -C $install_dir; \
    chmod 777 $install_dir/geckodriver;\
    ls -la $install_dir;\
    ln -s $install_dir/geckodriver /usr/local/bin/geckodriver;\
    chmod 777 /usr/local/bin/geckodriver;\
    chown root:root  $install_dir/geckodriver;\
    chown root:root  /usr/local/bin/geckodriver;\
    mkdir -p /.cache;\
    chmod 777 /.cache;\
    ls -la /.cache;\
    export PATH=$PATH:$install_dir;\
    mkdir $HOME/tmp;\
    export TMPDIR=$HOME/tmp geckodriver;\
    echo "seleniumuser:x:idxxx:group_idxxx:seleniumuser:/tmp:/bin/bash" >> /etc/passwd;\
    echo "installed geckodriver binary in $install_dir";)
ENV PATH="/opt/automation/data/webdriver:${PATH}"

################################################## ##


1
投票

对我来说,这是一个 Firefox 版本问题。我在 Ubuntu 22.04 上运行,问题出在 Firefox 的 snap 包上。解决方案是完全卸载firefox并从tar文件中安装必要的版本,甚至apt-get也是使用snap来安装的。更多详细信息这里


1
投票

主要问题是

.cache
.mozilla
文件夹,它们需要权限。数据在执行脚本的用户的个人资料中生成。

这个解决方案对我有用:

  1. 识别需要保存缓存的用户。就我而言是 www-dataSymfony的用户)。我在文件夹
    /tmp/
    中检查过它。 您可以看到文件夹的所有者,例如
    /tmp/Temp-276cddf8-d7c5-4a09...
    这些文件夹是由 火狐浏览器。
  2. 用户需要bash权限,所以要调整文件
    /etc/passwd
    来自
    www-data:33:33:www-data:/usr/sbin:/usr/sbin/nologin
    www-data:x:33:33:www-data:**/var/www**:**/bin/bash**
  3. 在路径中创建文件夹,在我的例子中是
    /var/www/
    (这个路径 位于文件中指定的用户路径
    /etc/passwd
    )。

mkdir /var/www/.cache

mkdir /var/www/.mozilla

chown www-data:www-data .cache

chown www-data:www-data .mozilla


0
投票

根据这个MR https://github.com/SeleniumHQ/docker-selenium/pull/485/files#diff-04c6e90faac2675aa89e2176d2eec7d8R43,启动容器时可以通过添加

 --shm-size 2g
来修复。

由于 Selenium 社区为 Firefox 提供了 docker 镜像,我认为直接使用他们的 docker 镜像,或者基于他们的 dockerfile 创建自己的镜像会是更好的选择,以减少出现此类问题的机会。


0
投票

对我来说,这个问题是由 selenium 创建 Web 驱动程序对象时启动的两个相同的 Firefox 进程引起的。看起来这导致了竞争条件,导致其他进程无法正确初始化。

为了解决这个问题,我在终端中运行了以下命令:

  1. 列出当前正在运行的 Firefox 进程:

    pgrep -laf firefox
    
  2. 终止相同的进程(终止列表中的第二个重复进程对我有用)

    kill -9 <PID>
    

0
投票

我在尝试在 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
© www.soinside.com 2019 - 2024. All rights reserved.