72

I installed google-chrome in a Docker, but when I run my Python 2 script of Selenium, it failed like this:

automation@1c17781fef0c:/topology-editor/test$ python test.py
Traceback (most recent call last):
  File "test.py", line 27, in <module>
    browser = webdriver.Chrome()
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/chrome/webdriver.py", line 69, in __init__
    desired_capabilities=desired_capabilities)
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 98, in __init__
    self.start_session(desired_capabilities, browser_profile)
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 185, in start_session
    response = self.execute(Command.NEW_SESSION, parameters)
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 249, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/errorhandler.py", line 194, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException: Message: unknown error: Chrome failed to start: crashed
  (Driver info: chromedriver=2.31.488763 (092de99f48a300323ecf8c2a4e2e7cab51de5ba8),platform=Linux 4.4.0-83-generic x86_64)

And if I run google-chrome directly in docker, it shows below:

automation@1c17781fef0c:/topology-editor/test$ google-chrome
Failed to move to new namespace: PID namespaces supported, Network namespace supported, but failed: errno = Operation not permitted
Trace/breakpoint trap (core dumped)
automation@1c17781fef0c:/topology-editor/test$

System:

$ uname -a
Linux 1c17781fef0c 4.4.0-83-generic #106-Ubuntu SMP Mon Jun 26 17:54:43 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
$ google-chrome --version
Google Chrome 60.0.3112.78
$ chromedriver --version
ChromeDriver 2.31.488763 (092de99f48a300323ecf8c2a4e2e7cab51de5ba8)
4
  • did you manage to do this? Commented Sep 26, 2017 at 19:45
  • @lub0v there are 2 choci to run chrome in docker:1. use selenium/standalone-chrome from selenium. 2. Build Dockerfile and install chrome, use headless way to run browser Commented Mar 22, 2019 at 2:55
  • 1
    github.com/joyzoursky/docker-python-chromedriver Commented Jul 2, 2020 at 18:50
  • 2024 Update: To make it work with Chrome for Testing, take a look at this: stackoverflow.com/a/78678053/7399485. It took me a long time to figure this out as most of the answers don't consider this. Commented Jun 27, 2024 at 13:55

4 Answers 4

103

You need to launch a standalone chrome browser

docker run -d -p 4444:4444 selenium/standalone-chrome

and then in your python script launch browser using Remote webdriver

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
driver = webdriver.Remote("http://127.0.0.1:4444/wd/hub", DesiredCapabilities.CHROME)

If you want you can also launch a Selenium Grid hub.

To do this as a django test do the following:

# docker-compose.yml

selenium:
  image: selenium/standalone-firefox
  ports:
  - 4444:4444

# project/app/test.py

from django.test import TestCase
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities


class SiteTest(TestCase):
    fixtures = [
        'app/fixtures/app.json',
        ...
    ]

    def setUp(self):
        self.browser = webdriver.Remote("http://selenium:4444/wd/hub", DesiredCapabilities.FIREFOX)

    def tearDown(self):
        self.browser.quit()

    def test_visit_site(self):
        self.browser.get('http://app:8000/')
        self.assertIn(self.browser.title, 'Home')

Note:

If you use webdriver.ChromeOptions|FirefoxOptions|etc then DesiredCapabalities import is not necessary:

from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_argument('--headless')  # example
driver = webdriver.Remote("http://127.0.0.1:4444/wd/hub", options=options)
Sign up to request clarification or add additional context in comments.

9 Comments

I've tried and run successfully with selenium/standalone-chrome. I failed this because I want to integrate chrome/selenium with another docker images we used before. I'll try the Remote way to run, thanks.
After a lot of searching in different places I found this to be the answer that worked best for me
I someone help me to understand why remote link is "127.0.0.1" ?
@MertTheGreat, that was updated by someone else but the 127.0.0.1 was just an example. In docker it would be selenium
|
70

You need to add the next lines to your Dockerfile:

# install google chrome
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
RUN apt-get -y update
RUN apt-get install -y google-chrome-stable

# install chromedriver
RUN apt-get install -yqq unzip
RUN wget -O /tmp/chromedriver.zip http://chromedriver.storage.googleapis.com/`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
RUN unzip /tmp/chromedriver.zip chromedriver -d /usr/local/bin/

# set display port to avoid crash
ENV DISPLAY=:99

# install selenium
RUN pip install selenium==3.8.0

Then your code should be like this. Especially you need to declare your driver like below:

from selenium import webdriver
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
driver = webdriver.Chrome(chrome_options=chrome_options)

driver.get('www.google.com')
screenshot = driver.save_screenshot('test.png')
driver.quit()

6 Comments

Nice work for your configuration with chrome_options to start chrome in headless mode
Thanks for the answer! I'd also mention that the Dockerfile could be improved to follow docs.docker.com/develop/develop-images/… and produce less layers/less size. For example, all RUN instructions could be combined into one. Also, we don't need to have /tmp/chromedriver.zip file as part of the image and we can remove it after unpacking. Two apt-get install commands can be combined into one.
I like how you downloaded a screenshot, so one can see it's actually working
It solves quite a few problems but it still doesn't work for me. My script does more than just taking a screenshot and I guess this introduces various new problems. First, there is the tab crash issue, and if you solve that then you have a timeout issue.
Worth making more explicit as I had issues with this but then resolved... First line of dockerfile should be FROM python:latest
|
14

For people coming through google search, here is the easiest workaround:

Dockerfile

FROM python:3.7

RUN apt-get update 
RUN apt-get install -y gconf-service libasound2 libatk1.0-0 libcairo2 libcups2 libfontconfig1 libgdk-pixbuf2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libxss1 fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils

#download and install chrome
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN dpkg -i google-chrome-stable_current_amd64.deb; apt-get -fy install

#install python dependencies
COPY requirements.txt requirements.txt 
RUN pip install -r ./requirements.txt 

#some envs
ENV APP_HOME /app 
ENV PORT 5000

#set workspace
WORKDIR ${APP_HOME}

#copy local files
COPY . . 

CMD exec gunicorn --bind :${PORT} --workers 1 --threads 8 main:app 

You will need to install chromedriver_binary pip package which I have added in requirements.txt as:

Flask==1.1.1
gunicorn==20.0.4
selenium==3.141.0
chromedriver-binary==79.0.3945.36

Then your main.py should be like:

from selenium import webdriver
import chromedriver_binary


chrome_options=webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("window-size=1400,2100") 
chrome_options.add_argument('--disable-gpu')

driver=webdriver.Chrome(chrome_options=chrome_options)

Now, build your Dockerfile using docker build -t <imagename> . and docker run --rm -p <yourPORT>:5000 <imagename>

2 Comments

FYI you will need to update chromedriver-binary to match the current stable version of chrome or this will error when you try to run "Message: session not created: This version of ChromeDriver only supports Chrome version 79"
Yes @LeonKyriacou I agree. Here is how I automated the version matching between google chrome and the chromedriver : wget -O LATEST_RELEASE chromedriver.storage.googleapis.com/LATEST_RELEASE && \ latest=$(cat LATEST_RELEASE) && \ sed -i "s/XXXX/$latest/g" requirements.txt && \
0

I assume you need to run it in headless mode

https://developers.google.com/web/updates/2017/04/headless-chrome

this is how I do it in ruby

capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: {args: %w[ no-sandbox headless disable-gpu window-size=1280,1000 ]})

Capybara::Selenium::Driver.new(app, :browser => :chrome, http_client: client, desired_capabilities: capabilities)

You can pretty much adapt your code in python

also consider installing some font libriaries that chrome needs to run on headless

RUN apt-get update && \
    apt-get -qq -y install  libxpm4 libxrender1 libgtk2.0-0 libnss3\ 
       libgconf-2-4  libpango1.0-0 libxss1 libxtst6 fonts-liberation\ 
       libappindicator1 xdg-utils

RUN apt-get -y install \
               xvfb gtk2-engines-pixbuf \
               xfonts-cyrillic xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable \
               imagemagick x11-apps zip

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.