Open Chrome with Rails Feature Spec using Docker

Viewed 588

I can't figure out how to make the feature specs work when running non-headless feature specs for Rails in Docker. I can get the Chrome to open, but I'm getting ERR_EMPTY_RESPONSE (basically, it's blank)

The whole source code is available at: https://github.com/amree/blog-example

Commands:

# chromedriver on the host
chromedriver --whitelisted-ips

# build the image
docker build -t blog_base --progress=plain --secret id=bundle_credentials,src=.env.development .

# run the test
docker compose run --rm web bundle exec rspec spec/features/user_creates_post_spec.rb
# spec/support/capybara.rb
require "capybara/rspec"
require "selenium-webdriver"

Capybara.server = :puma, { Silent: false }

# Setup rspec
RSpec.configure do |config|
  config.before(:each, type: :system, js: true) do
    Capybara.server_host =  "0.0.0.0"
    Capybara.server_port = "31337"
    Capybara.app_host    = "http://127.0.0.1:31337"


    driven_by :selenium, using: :chrome, options: {
      browser: :remote,
      # Couldn't use http://host.docker.internal:9515 for some reason, so, I just
      # use my current wifi IP here
      url: "http://192.168.1.244:9515",
      desired_capabilities: :chrome
    }
  end
end
# Dockerfile
FROM ruby:2.6.3

RUN apt-get update \
  && apt-get install -y --no-install-recommends \
    curl \
    build-essential \
    libpq-dev \
  && curl -sL https://deb.nodesource.com/setup_16.x | bash - \
  && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
  && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
  && apt-get install -y nodejs \
  && rm -rf /var/lib/apt/lists/*

WORKDIR /app

RUN gem install rails:6.1.4.4 bundler:2.3.4
COPY Gemfile* /app
COPY bundle_install.sh .
RUN --mount=type=secret,id=bundle_credentials ./bundle_install.sh

RUN npm install -g yarn
COPY package.json /app
COPY yarn.lock /app
RUN yarn install

ADD . /app

EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
# docker-compose.yml
services:
  db:
    image: postgres:14.1-alpine
    volumes:
      - db:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=password

  redis:
    image: redis:6.2-alpine
    command: redis-server
    volumes:
      - redis:/data

  chrome:
    image: blog_base
    command: bash -c "/usr/bin/true"
    ports:
      - "31337:31337"
    volumes:
      - .:/app
      - bundle:/bundle
      - node_modules:/app/node_modules
    environment:
      - BUNDLE_PATH=/bundle
      - DATABASE_USERNAME=postgres
      - DATABASE_PASSWORD=password
      - DATABASE_HOST=db
      - REDIS_URL=redis://redis:6379
      - RAILS_ENV=test
      - RACK_ENV=test
    depends_on:
      - db

  selenium:
    image: selenium/standalone-chrome

volumes:
  db: {}
  bundle: {}
  node_modules: {}
  redis: {}

The error:

2022-01-11 16:04:14 WARN Selenium [DEPRECATION] [:desired_capabilities] :desired_capabilities as a parameter for driver initialization is deprecated. Use :capabilities with an Array value of capabilities/options if necessary instead.
2022-01-11 16:04:14 WARN Selenium [DEPRECATION] [:browser_options] :options as a parameter for driver initialization is deprecated. Use :capabilities with an Array of value capabilities/options if necessary instead.
Capybara starting Puma...
* Version 5.5.2 , codename: Zawgyi
* Min threads: 0, max threads: 4
* Listening on http://0.0.0.0:31337
F

Failures:

  1) User creates post successfully
     Failure/Error: visit posts_path

     Selenium::WebDriver::Error::UnknownError:
       unknown error: net::ERR_CONNECTION_REFUSED
         (Session info: chrome=97.0.4692.71)

     [Screenshot Image]: /app/tmp/screenshots/failures_r_spec_example_groups_user_creates_post_successfully_168.png


     # 0   chromedriver                        0x000000010bcefe69 chromedriver + 5160553
     # 1   chromedriver                        0x000000010bc7a593 chromedriver + 4679059
     # 2   chromedriver                        0x000000010b82e2c8 chromedriver + 172744
     # 3   chromedriver                        0x000000010b8281b7 chromedriver + 147895

error

1 Answers

When launching Chrome don't point it to the local address 127.0.0.1 because Docker starts the container up with its own IP (unless explicitly specified).

You have two options:

  1. Run the app in a container and use the hostname

Set the launch URL to the hostname of the Docker Container.

The value would be http://chrome:31337, where chrome is the container name used in the Docker Compose file.

  1. Allow the docker container to access the host ports. (If you are running the app outside of docker)

To do this add the following line to the selenium container

extra_hosts:
- "host.docker.internal:host-gateway"

Then set the value to http://host.docker.internal:31337.

Related