There are numerous forum posts and people having issues getting their feature specs running in CircleCI using selenium and headless chrome, but it’s not as complicated as you might expect.

NOTE: This configuration is for circle 2.0, using docker images.

1. Circle.yml config

Notice the env variable: SELENIUM_DRIVER_URL and selenium’s chrome docker image which uses the variable.

# .circleci/config.yml
version: 2
      - image: circleci/ruby:2.4.1-node
          RAILS_ENV: test
          SELENIUM_DRIVER_URL: http://localhost:4444/wd/hub
      - image: circleci/postgres:9.6.3-alpine
      - image: selenium/standalone-chrome:3.11.0
    # ...

2. Configure Capybara

In the capybara config, I added a conditional to look for the env var. If it’s found it will use a different config than the local one.

# spec/support/capybara.rb
require 'capybara/rspec'
require 'selenium/webdriver'

Capybara.register_driver :chrome do |app|, browser: :chrome)

Capybara.register_driver :headless_chrome do |app|
  capabilities =
    chromeOptions: { args: %w(headless no-sandbox) }

  if ENV['SELENIUM_DRIVER_URL'].present?
      browser: :remote,
      url: ENV.fetch('SELENIUM_DRIVER_URL'),
      desired_capabilities: capabilities
  else app,
      browser: :chrome,
      desired_capabilities: capabilities

Capybara.javascript_driver = :headless_chrome

And that’s it! I wrestled with getting the specs running circle for a while, and after googling and trying tons of more convoluted solutions, this approched seemed to work best.

Let me know if you have any suggestions or see any issues with this configuration.