7

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.

Guillaume Georges
  • 3,878
  • 3
  • 14
  • 32
  • Would [this GitHub issue comment](https://github.com/canonical/bundle-kubeflow/issues/457#issuecomment-1133457475) be useful? – ErikMD Jun 01 '22 at 22:55
  • According to this answer: https://stackoverflow.com/a/49800671/3099733 , you may need to check the RAM of your server and try to increase the total RAM to at least 2 GB – link89 Jun 04 '22 at 05:29

7 Answers7

4

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
  • Please upvote this answer. The `/etc/apt/preferences.d/mozilla-firefox` file was genius, it got rid of my `/usr/bin/firefox: 12: xdg-settings: not found` message when I asked firefox its version, and the "marionette" error as in the OP's question. – John Jun 18 '23 at 18:01
2

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

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

Kiyarash
  • 2,437
  • 7
  • 32
  • 61
Jesse Guo
  • 21
  • 3
  • The container is running as user 1000. In /etc/passwd, there's already a line for this user : `1000:x:1000:0:1000 user:/:/sbin/nologin` So I only did what you suggested in 1. And it didn't change anything. – Guillaume Georges Jul 01 '22 at 11:33
  • what's your geckodriver.log? below is my Dockerfile to install geckodriver, copy here for your reference: – Jesse Guo Jul 04 '22 at 03:29
1

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.

  • 1
    solved the issue for me, now at least able to start in headless mode. You can keep snap, but need to point to binary: options.binary = "/home/maksim/Downloads/firefox/firefox" – Beliaev Maksim Jan 27 '23 at 21:54
1

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

  • You are a life saviour! I couldn't get python script to work in pair with zabbix `system.run` element because of `Get value from agent failed: ZBX_TCP_READ() timed out` and `zabbix_sender: send value error: ZBX_TCP_READ` errors. I executed `sudo -u zabbix /bin/bash` (or `su zabbix -c /bin/bash` if you are not root), executed my script, got an error `selenium.common.exceptions.TimeoutException: Message: Failed to read marionette port`. – Kyo Aug 26 '23 at 09:01
  • After that I have seen your answer and I have got an idea how to apply it to my problem: I executed `cat /etc/passwd`, saw a line `zabbix:x:997:994:Zabbix Monitoring System:/var/lib/zabbix:/sbin/nologin`, I checked `/var/lib/zabbix` path and found out that there wasn't such a directory. Thus I executed: `mkdir /var/lib/zabbix`, `mkdir /var/lib/zabbix/.mozilla`, `mkdir /var/lib/zabbix/.cache`, `chown -R zabbix:zabbix /var/lib/zabbix`. And the script now executes fine and zabbix element works without any problem. – Kyo Aug 26 '23 at 09:02
0

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.

link89
  • 1,064
  • 10
  • 13
  • It doesn't solve my issue. And I fail to understand why it would solve it. The error I'm getting is not the same as the one mentionned in the issue you linked. And also, docker is able to run my image without any issue, where the `USER 1000` instruction is commented. So it seems to me it's more an issue with permissions that are not granted to a non root user. Permissions to allocate a port, for instance. But I don't see how or why it would be related to memory allocation. – Guillaume Georges Jun 07 '22 at 12:12
0

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>
    
Errigal
  • 15
  • 6
0

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
rajaie
  • 1