Build a Docker Image for Ruby, Watir Webdriver, Shopify API, Chrome, and Firefox

Build a Docker Image for Ruby, Watir Webdriver, Shopify API, Chrome, and Firefox

Docker containers have become a really convenient way of running an automated test suite. Containers can be quickly spun up, easily torn down, and since you only pay for the time they’re running, can be cheaply hosted in the cloud.

Lets take a look at how to build a Docker container that includes everything we need to run a UI test framework using Ruby and Selenium WebDriver.

Dockerfiles

When building a container, Docker follows instructions within a file called a Dockerfile. The Dockerfile outlines the individual commands needed to install and setup all the stuff we want in our container.

Start With a Base Image

There are a ton of different Unix distributions you can use to build your Docker container. Even though running your Docker container can be cheap when run in the cloud, or free when run within your own data center or test lab, you still need to “pay” a resource price when it comes to things like bandwidth to copy the container file and time to start it.

It’s in our best interest to keep our Docker container as small as possible. Alpine Linux is a relatively small Linux distribution. It has a small footprint that makes it perfect for use with Docker because it helps to keep the container file size small.

FROM alpine:latest

Package Repositories

Next we need to add specific Alpine package repositories. The stock Alpine image only knows about the repositories for the Alpine OS itself. If you want to install third-party packages, you’ll have to set the location of those repositories yourself.

If you’re used to using Ubuntu, you’ll know that the default package manager is apt-get. In the Alpine Linux world, the default package manager is called apk.

# Point to specific Alpine Package repositories for Chromium and Firefox.
RUN apk update && apk upgrade \
    && echo @latest-stable http://nl.alpinelinux.org/alpine/latest-stable/community >> /etc/apk/repositories \
    && echo @latest-stable http://nl.alpinelinux.org/alpine/latest-stable/main >> /etc/apk/repositories \
    && echo @edge-testing http://dl-cdn.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories \
    && echo @edge-main http://dl-cdn.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories

Installing Ruby

Next lets install the Ruby development environment.

# Install Ruby dev environment
RUN apk add --no-cache build-base
RUN apk add --no-cache libffi-dev
RUN apk add --no-cache ruby-dev
RUN apk add --no-cache ruby-rdoc
RUN apk add --no-cache ruby-webrick@latest-stable
RUN apk add --no-cache zlib-dev

Install The Browsers

When running your tests within Docker, you won’t have access to a windowed Desktop. This forces you to run your test in headless mode.

The only two desktop browsers you can install in Docker that support headless mode are Firefox and Chrome.

# Install Chromium
RUN apk add --no-cache chromium-chromedriver
RUN apk add --no-cache chromium@latest-stable
RUN apk add --no-cache harfbuzz@latest-stable
RUN apk add --no-cache nss@latest-stable

# Install Firefox and the Gechodriver
RUN apk add --no-cache icu-libs@edge-main
RUN apk add --no-cache firefox@edge-testing
RUN wget https://github.com/mozilla/geckodriver/releases/download/v0.24.0/geckodriver-v0.24.0-linux64.tar.gz && \
	tar -zxvf geckodriver-v0.24.0-linux64.tar.gz && \
	mv ./geckodriver /usr/local/bin/ && \
	chmod a+x /usr/local/bin/geckodriver

Ruby Gems Needed By Our Tests

The test framework we built at Rewind needs to interact with Shopify and BigCommerce. We do this using their respective APIs.

The UI tests also use Selenium WebDriver. In this case, we’re using the Watir library, which wraps WebDriver and offers improved usability.

Lets run the Ruby gem commands to install those dependencies.

# Install Ruby gems required by the test framework.
RUN gem install rake
RUN gem install minitest
RUN gem install minitest-reporters
RUN gem install watir:6.16
RUN gem install shopify_api
RUN gem install bigcommerce
RUN gem install bigdecimal
RUN gem install aws-sdk-s3

Cleanup

Now lets delete any leftover packages and other temporary files from inside the image.

# Clean up leftovers to help keep the final image small.
RUN rm -rf /var/lib/apt/lists/* \
    /var/cache/apk/* \
    /usr/share/man \
    /tmp/*

Include Our Ruby Test Scripts

Lets pull into the container the WebDriver tests and any Ruby code we’ve written. This assumes the Dockerfile is sitting in the same directory as our WebDriver tests.

This command will copy a local directory called ‘webdriver-tests‘ to the root (/) of the Docker container.

# Copy the automated tests into the container.
ADD . webdriver-tests

Create a Unix User

We want to avoid running our tests as the Unix ‘root’ user, so lets create a user our Ruby tests will run as. Lets call the user ‘webdriver‘ and make him the owner of the ‘webdriver-tests’ directory.

# Add 'webdriver' as a user
RUN adduser -D webdriver \
    && chown -R webdriver:webdriver /webdriver-tests

# Switch to non-privileged user 'webdriver'
USER webdriver
WORKDIR /webdriver-tests

Environment Variables

Once we’ve switched to the ‘webdriver’ user, we need to set some environment variables to help the Ruby code find the Chrome browser.

# Set the environment variables for the Chromium browser.
ENV CHROME_BIN=/usr/bin/chromium-browser \
    CHROME_PATH=/usr/lib/chromium/

The Final Product

You’ll notice how I was using a bunch of individual RUN commands when adding each package. This is pretty inefficient and causes the Docker image to be larger than it needs to be.

So why do it? Docker caches the result of each line. When running the build command on the Dockerfile, Docker will check its cache if it has previously run that command. If so, it will simply apply the cached result of a previous run for that command. This reduces the time it takes to build the Docker file. This is very useful when debugging problems with your Dockerfile.

If we had used a single RUN command to install all of our packages, Docker would have had to reinstall each package on that line even if a single item had been changed.

Once we’ve got our Dockerfile producing the container that we want, we can condense all of those RUN commands into just a few lines. This will reduce the number of cached layers further reducing the size of our container.

Here’s our optimized Dockerfile.

FROM alpine:latest
# Point to specific Alpine Package repositories for Chromium and Firefox.
RUN apk update && apk upgrade \
&& echo @latest-stable http://nl.alpinelinux.org/alpine/latest-stable/community >> /etc/apk/repositories \
&& echo @latest-stable http://nl.alpinelinux.org/alpine/latest-stable/main >> /etc/apk/repositories \
&& echo @edge-testing http://dl-cdn.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories \
&& echo @edge-main http://dl-cdn.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories
# Install Ruby dev environment
RUN apk add --no-cache build-base libffi-dev ruby-dev ruby-rdoc ruby-webrick@latest-stable zlib-dev
# Install Chromium
RUN apk add --no-cache chromium-chromedriver chromium@latest-stable harfbuzz@latest-stable nss@latest-stable
# Install Firefox and the Gechodriver
RUN apk add --no-cache icu-libs@edge-main firefox@edge-testing
RUN wget https://github.com/mozilla/geckodriver/releases/download/v0.24.0/geckodriver-v0.24.0-linux64.tar.gz && \
tar -zxvf geckodriver-v0.24.0-linux64.tar.gz && \
mv ./geckodriver /usr/local/bin/ && \
chmod a+x /usr/local/bin/geckodriver
# Install Ruby gems required by the test framework.
RUN gem install rake minitest minitest-reporters watir:6.16 shopify_api bigdecimal aws-sdk-s3
# Clean up leftovers to help keep the final image small.
RUN rm -rf /var/lib/apt/lists/* \
/var/cache/apk/* \
/usr/share/man \
/tmp/*
# Copy the automated tests into the container.
ADD . webdriver-tests
# Add 'webdriver' as a user
RUN adduser -D webdriver \
&& chown -R webdriver:webdriver /webdriver-tests
# Switch to non-privileged user 'webdriver'
USER webdriver
WORKDIR /webdriver-tests
# Set the environment variables for the Chromium browser.
ENV CHROME_BIN=/usr/bin/chromium-browser \
CHROME_PATH=/usr/lib/chromium/
view raw dockerfile hosted with ❤ by GitHub

 

Leave a Reply