This is a rehash of my Alpine Linux version of this post. I’ll skip the fluff here and jump straight to the good stuff.
The packages needed for Chromedriver are:
libnss3 libnspr4
The packages needed for Chrome are:
libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2
(There’s also a package called chromium-shell
that installs all of these necessary dependencies, and at least half a kitchen sink too. The install time for this package is very long.)
The Dockerfile
is therefore:
FROM ruby:3.2.2
RUN apt-get update && apt-get install libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2
# OR this, but the install time is much longer:
# RUN apt-get update && apt-get install chromium-shell
RUN adduser --disabled-password --gecos "" app
COPY --chown app:app . /app
WORKDIR /app
USER app
RUN bundle config set --local path vendor/bundle
RUN bundle install
CMD bundle exec irb
And we can then build and run this image:
docker build . -t ubuntu-selenium
docker run -it ubuntu-selenium
And confirm it works by running:
Bundler.require
Selenium::WebDriver.logger.level = Logger::DEBUG
options = ::Selenium::WebDriver::Chrome::Options.new
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
options.add_argument("--disable-gpu")
Selenium::WebDriver.for :chrome, capabilities: options
This output should include things like a check for both Chrome + ChromeDriver, which will fail:
DEBUG Selenium [:selenium_manager] Checking chromedriver in PATH
DEBUG Selenium [:selenium_manager] Running command: chromedriver --version
DEBUG Selenium [:selenium_manager] Output: ""
DEBUG Selenium [:selenium_manager] chromedriver not found in PATH
DEBUG Selenium [:selenium_manager] Checking chrome in PATH
DEBUG Selenium [:selenium_manager] Running command: which chrome
DEBUG Selenium [:selenium_manager] Output: ""
DEBUG Selenium [:selenium_manager] chrome not found in PATH
DEBUG Selenium [:selenium_manager] chrome has not been discovered in the system
(The chrome one fails here, as chromium
has installed Chrome at /usr/bin/chromium
.)
After that, we’ll see log lines for downloads of Chrome + ChromeDriver:
DEBUG Selenium [:selenium_manager] Reading metadata from https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json
DEBUG Selenium [:selenium_manager] Required browser: chrome 116.0.5845.96
DEBUG Selenium [:selenium_manager] Downloading chrome 116.0.5845.96 from https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/116.0.5845.96/linux64/chrome-linux64.zip
DEBUG Selenium [:selenium_manager] chrome 116.0.5845.96 has been downloaded at /home/app/.cache/selenium/chrome/linux64/116.0.5845.96/chrome
DEBUG Selenium [:selenium_manager] Reading metadata from https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json
DEBUG Selenium [:selenium_manager] Required driver: chromedriver 116.0.5845.96
DEBUG Selenium [:selenium_manager] Driver URL: https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/116.0.5845.96/linux64/chromedriver-linux64.zip
DEBUG Selenium [:selenium_manager] Driver path: /home/app/.cache/selenium/chromedriver/linux64/116.0.5845.96/chromedriver
DEBUG Selenium [:selenium_manager] Browser path: /home/app/.cache/selenium/chrome/linux64/116.0.5845.96/chrome
Importantly, this shows version 116.0.5845.96 for both Chrome + ChromeDriver. We want these to match for compatibility reasons. As Chrome releases newer versions, the version that’s downloaded here will differ.
Then we’ll see ChromeDriver starting up:
DEBUG Selenium [:selenium_manager] Browser path: /home/app/.cache/selenium/chrome/linux64/116.0.5845.96/chrome
DEBUG Selenium [:driver_service] port prober could not bind to ::1:9515 (Address not available - bind(2) for "::1" port 9515)
DEBUG Selenium [:driver_service] Executing Process ["/home/app/.cache/selenium/chromedriver/linux64/116.0.5845.96/chromedriver", "--port=9515"]
DEBUG Selenium [:process] Starting process: ["/home/app/.cache/selenium/chromedriver/linux64/116.0.5845.96/chromedriver", "--port=9515"] with {[:out, :err]=>#<IO:<STDOUT>>, :pgroup=>true}
DEBUG Selenium [:process] -> pid: 28
2023-08-22 05:46:27 DEBUG Selenium [:driver_service] polling for socket on ["127.0.0.1", 9515]
Starting ChromeDriver 116.0.5845.96 (1a391816688002153ef791ffe60d9e899a71a037-refs/branch-heads/5845@{#1382}) on port 9515
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
[1692683187.222][SEVERE]: bind() failed: Address not available (99)
ChromeDriver was started successfully.
The “address not available (99)” error here is because ChromeDriver is trying to bind to ::1:9515
, but this Docker image is not setup with IPv6 support, so that will fail.
Finally, we’ll see some JSON requests to POST session
going back and forth from 9515
, indicating ChromeDriver’s opening a Chrome window and that’s succeeding.
DEBUG Selenium [:command] -> POST session
DEBUG Selenium [:command] >>> http://127.0.0.1:9515/session | {"capabilities":{"alwaysMatch":{"browserName":"chrome","goog:chromeOptions":{"args":["--headless","--no-sandbox","--disable-dev-shm-usage","--disable-gpu"],"binary":"/home/app/.cache/selenium/chrome/linux64/116.0.5845.96/chrome"}}}}