Guillaume Georges
Guillaume Georges

Reputation: 4020

"Failed to read marionette port" when Running Selenium + geckodriver + firefox as a non-root user in a Docker container

I'm running selenium tests inside a docker container, with Firefox and Geckodriver. When running that container as root, everything works fine.

When running the container as non-root user (USER 1000), the driver fails to initialize :

[[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)

Relevant parts of my 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

I even added some chmod / chown to try and fix some permissions issues with firefox or 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

And finally the USER instruction to run the container as non-root

USER 1000

I do not manually install selenium. It's a maven dependency of the project I'm installing where my tests sources are.

Upvotes: 14

Views: 18607

Answers (7)

Jesse Guo
Jesse Guo

Reputation: 21

I met the same issue recently, and tried to solve it by the following

Message: Failed to read marionette port

  1. in Dockerfile create a directory /.cache
mkdir -p /.cache;\

and give write permission to /.cache directory

chmod 777 /.cache;\
  1. if you run docker with specified user id (i.e. Jenkins id), then you need to add some username with the userid and groupid in yourcontainername:/etc/passwd
echo "somename:x:1234:1235:somename:/tmp:/bin/bash" >> /tmp/passwd 

firefox started

'/.cache/dconf': Permission denied

below is my Dockerfile to install geckodriver, copy here for your reference, hopefully it helps! #######################################

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}"

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

Upvotes: 2

NoPurposeInLife
NoPurposeInLife

Reputation: 425

You may also install firefox via apt, this step fixed it for me. (https://github.com/FortyNorthSecurity/EyeWitness/issues/604 and https://www.omgubuntu.co.uk/2022/04/how-to-install-firefox-deb-apt-ubuntu-22-04)

Step 1: Remove the Firefox Snap by running the following command in a new Terminal window:

sudo snap remove firefox

Step 2: Add the (Ubuntu) Mozilla team PPA to your list of software sources by running the following command in the same Terminal window:

sudo add-apt-repository ppa:mozillateam/ppa

Step 3: Next, alter the Firefox package priority to ensure the PPA/deb/apt version of Firefox is preferred. This can be done using a slither of code from FosTips (copy and paste it whole, not line by line):

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

Step 4: Since you’ll (hopefully) want future Firefox upgrades to be installed automatically, Balint Reczey shares a concise command on his blog that ensures it happens:

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

Step 5: Finally, install Firefox via apt by running this command:

sudo apt install firefox

Upvotes: 28

Carlos Arranz
Carlos Arranz

Reputation: 21

The main problem is .cache and .mozilla folders, which need permissions. The data is generated in the profile of the user who execute the script.

This solution worked for me:

  1. Identify the user who needs to save the cache. In my case it was www-data (the user of Symfony). I checked it in the folder /tmp/. You can see the owner of folders like /tmp/Temp-276cddf8-d7c5-4a09... These folders are generated by Firefox.
  2. The user needs bash permissions, so you have to adjust the file
    /etc/passwd from www-data:33:33:www-data:/usr/sbin:/usr/sbin/nologin to www-data:x:33:33:www-data:**/var/www**:**/bin/bash**
  3. Create the folders in the path, in my case is /var/www/ (this path is located in the user path specified in the file /etc/passwd).

mkdir /var/www/.cache

mkdir /var/www/.mozilla

chown www-data:www-data .cache

chown www-data:www-data .mozilla

Upvotes: 1

Bhavya Peshavaria
Bhavya Peshavaria

Reputation: 361

For me, it was a firefox version issue. I was running on Ubuntu 22.04 and the issue was with the snap package of firefox. The solution was to uninstall firefox completely and install the necessary version from the tar file, even apt-get was using snap to install. More detailed info here.

Upvotes: 1

rajaie
rajaie

Reputation: 11

I was running into the same issue trying to launch a headless Firefox inside a Docker container on Kubernetes. What solved it for me was adding the code below to my Dockerfile

RUN groupadd ffgroup --gid 2000  \
    && useradd ffuser \
    --create-home \
    --home-dir /tmp/ffuser \
    --gid 2000 \
    --shell /bin/bash \
    --uid 1000

and then adding the following to the container's spec:

            securityContext:
              runAsNonRoot: true
              runAsUser: 1000
              runAsGroup: 2000
              fsGroup: 2000

Upvotes: 1

Errigal
Errigal

Reputation: 15

For me the issue was caused by two identical firefox processes starting when selenium creates the web driver object. It looks like this caused a race condition, preventing the other process from initialising properly.

To solve this I ran the following commands in the terminal:

  1. List the firefox processes currently running:

    pgrep -laf firefox
    
  2. Kill the identical process (killing the second duplicate process in the list worked for me)

    kill -9 <PID>
    

Upvotes: 0

link89
link89

Reputation: 1823

According to this MR https://github.com/SeleniumHQ/docker-selenium/pull/485/files#diff-04c6e90faac2675aa89e2176d2eec7d8R43, it may be fixed by add --shm-size 2g when you start the container.

As the Selenium community provide docker image for Firefox, I think it would be a better choice to use their docker image directly, or create your own based on their dockerfile to reduce the chance of having problem like this.

Upvotes: 0

Related Questions