Just a few Docker Compose 3 techniques for integrating:
- Rails 5.0 development & Travis CI tests
- Caching of bundler gems into a Docker volume which persists across builds and Gemfile changes
- A Selenium Chrome standalone instance running Capybara tests, and a VNC connection to interact with the test browser session
These insights took a while to grasp — so I'm sharing in case someone else finds it useful.
New to Docker & Rails? Unfamiliar with the issues surrounding the topics above? Start with the links in References.
- Install Docker 17.03.0-ce+. This should also install Docker Compose 1.11.2+.
- Verify versions:
docker -v; docker-compose -v;
- Install VNC Viewer to view & interact with selenium sessions that would otherwise be headless.
This base Rails app is very simple since the focus here is on docker.
- Was setup with
rails new app --skip-active-record
. The database was skipped to stay lightweight. - It has one root path route to the WelcomeController which renders "Hello World!" from
views/welcome/index.html.erb
docker-compose build
Builds images.
docker-compose up
Installs gems, launches web server.
open http://localhost:3000
Once the server is up, the root page can be seen on your local machine.
docker-compose test
Ensure the services are already 'up' in another terminal, or in detached mode, before running tests.
vnc://localhost:5900 password:secret
To watch the selenium tests run, use VNC to connect to the Selenium service. VNC Viewer works well, and on OS X Screen Sharing app is built-in. To interact and debug a browser session, add byebug
into the test to stop the driver.
Bundler installs and keeps track of all the gem libraries. Keeping docker container build times low is not trivial when bundler is involved. It took some time & research to optimize bundler's cache, so is worth an explanation. Credit to the unboxed team for this bundler cache technique — I've made some changes to make it compatible for Docker Compose 3 (which doesn't support volume_from
). The gist of it:
Dockerfile
:
ENTRYPOINT ["/docker-entrypoint.sh"]
allows a shell script to run before any relative containers execute a command.ENV BUNDLE_PATH=/bundle BUNDLE_BIN=/bundle/bin GEM_HOME=/bundle
configures a new installation path for future bundler installs, and binstubs.ENV PATH="${BUNDLE_BIN}:${PATH}"
allows bundler's binstubs to be executed withoutbundle exec
(i.e.puma
)
docker-entrypoint.sh
:
- Ensures all gems are installed before the web services boot up. This happens everytime
docker-compose up
executes. - Gems are installed to
/bundle
in the docker instance because of the definedBUNDLE_PATH
env var above. bundle install --binstubs="$BUNDLE_BIN"
installs the gems and stub commands are available because they were defined on PATH above.
docker-compose.yml
:
version: '3.1'
Volume syntax changed a bit between 2 and 3 (volume_from was removed)services:web:volumes:
definesbundle_cache:/bundle
, and thenvolumes:bundle_cache
persists it across builds. This reduces build times for local development. 🎉- When installing a new gem, or changing branches which have different gems — just stop the docker services and restart it. Or execute
bundle install
on the container. The old gems are already cached, and only new gems will be installed.
docker-compose.override.yml
- This file is automatically used during a standard
docker-compose up
. - Has a muliline
services:web:command
that starts the development (port 3000) & test (port 3001) servers. This could move that into a script file, but I like having a flatter architecture, and there's one less file to chase down. - Runs dedicated test server which is bound to the test database to debug the test environment, and fewer differences between dev & CI environments.
- Exposes web ports to host machine so you can visit 'http://localhost:3000' for development server, and 'http://localhost:3001' for test server.
- See Travis CI section for why the command and ports had to be split out into an override file (vs. just putting directly into the
docker-compose.yml
file.
Gemfile
- Has
selenium-webdriver
andminitest-rails-capybara
in the:test
group.
docker-compose.yml
- Defines
services:selenium
with theselenium/standalone-chrome-debug
image - The VNC service included with the debug is really useful for debugging (see commands section).
- Defines several enviornment variables which help link Capybara to the Docker network:
SELENIUM_HOST SELENIUM_PORT TEST_APP_HOST TEST_PORT
test/test_helper.rb
- Uses the env variables defined above in the Capybara configuration.
test/acceptance/welcome_page_test.rb
Shows a simple test case to visit the root path, and confirms 'Hello World!' is rendered.
docker-compose.ci.yml
- Command launches the test server.
- Configures ports that are only exposed to the Docker network — not to the host machine. Travis was blocking some of the external ports.
- This override file is executed in
.travis.yml
as:docker-compose -f docker-compose.yml -f docker-compose.ci.yml up -d
New to Docker & Rails? Unfamiliar with the issues surrounding the topics above? Start here. Much of this repo is an derivative & build upon the content of these quality resources:
Docker & Rails:
- Dockerize a Rails 5, Postgres, Redis, Sidekiq and Action Cable Application with Docker Compose (Nick Janetakis)
Docker & Bundler:
- Make bundler fast again in Docker Compose (Brad Gessler)
- Development Re-bundling in Dockerland (Charlie Egan)
Docker & Selenium:
- Dockerized Rails Capybara Tests On Top Of Selenium (Alfredo Motta)
- Docker container for running browser tests (George Diaz)
Docker & Travis:
- Travis - Using Docker in Builds (TravisCI)
- Managing Docker & Docker Compose versions on Travis (Grayson Koonce)
Copyright © JFMK, LLC Released under the MIT License.