Featured image of post Running Selenium + Chromedriver in Docker

Running Selenium + Chromedriver in Docker

As a developer who has used both Selenium and Docker a lot in the past, I thought running Selenium with Chromedriver in Docker would be pretty straight-forward. I quickly made a Debian image with Python and Chromedriver installed, and tried to run a few test cases.

The test starts successfully, so I go to grab a lunch.

However, when I come back, I see that the test has failed with the following error:

1
INTERNALERROR> selenium.common.exceptions.InvalidSessionIdException: Message: invalid session id

I’ve seen this error in the past. This means Chromedriver was doing its job normally, but Chrome had suddenly crashed for some reason.

After executing the test for a few times and monitoring resource usage, I came to a conclusion that Chrome was simply consuming too much memory.

Solution: don’t use shared memory

Turns out the problem is that the shared memory size in the docker container is too small. The default shared memory size in Docker is 64MB, which is not enough for Chrome to run properly.

Conveniently, Chrome has a start-up option --disable-dev-shm-usage that disables the use of /dev/shm for shared memory. instead, it will use the /tmp directory.

Info

Using /tmp for shared memory is not as fast as using /dev/shm, but from what I tested, the performance degradation is not noticeable for most cases.

Example Chrome options

Here is a full example of running Chromedriver in a docker container:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from selenium import webdriver
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait

opts = webdriver.ChromeOptions()
opts.add_argument('--headless')
opts.add_argument("--no-sandbox")
opts.add_argument("--disable-setuid-sandbox")
opts.add_argument("--disable-gpu")
opts.add_argument("--disable-dev-shm-usage")
opts.add_argument("--window-size=1920,1080")
service = webdriver.ChromeService(executable_path = '/usr/bin/chromedriver')
driver = webdriver.Chrome(service=service, options=opts)
Warning

Here, I’m using the --no-sandbox and --disable-setuid-sandbox options to run chromedriver as root.
I’m doing this because this test program runs in a trusted environment, but it is not recommended to do this if you access untrusted websites.
An alternative would be to create a new user in the docker container and run chromedriver without these options.

Built with Hugo
Theme Stack designed by Jimmy