How to Upgrade Any Rails Application Using Docker
Every time we start a new Rails upgrade project, we need to setup a whole new environment in our local machines. Sometimes that leads us down the rabbit hole which ends up breaking our environment for other client projects.
That's why we decided to use Docker and docker-compose for all of our client projects. This year I had the opportunity to share our process in a series of workshops: Upgrade Rails 101: The Roadmap to Smooth Upgrades
In order to set up all the services I used this
version: "2" services: cache: image: memcached:1.4-alpine ports: - "11211:11211" restart: always db: environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: image: postgres:9.6 expose: - "5432" app: stdin_open: true tty: true restart: always env_file: .env.test build: . ports: - "8080:8080" depends_on: - db - cache volumes: - .:/usr/src/app:consistent
In order to setup the app service, I defined a
Dockerfile like this:
FROM ruby:2.3.8-jessie RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - RUN apt-get update -yqq \ && apt-get install -yqq --no-install-recommends \ build-essential \ postgresql-client-9.6 \ nodejs \ vim \ libpq-dev \ qt5-default \ libqt5webkit5-dev \ && apt-get -q clean RUN apt-get update WORKDIR /usr/src/app COPY Gemfile Gemfile.lock ./ RUN gem install bundler -v=1.17.3 RUN bundle install COPY . .
As every other Rails application, it is not 100% standard. For instance, to
setup the database you need to load the
structure.sql file. So I decided to
write a quick script (
bin/docker-setup) to setup the test database:
#!/usr/bin/env ruby require 'pathname' # path to your application root. APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) Dir.chdir APP_ROOT do puts "== Creating databases ==" system "rake db:create" system "psql -q -h db -U postgres -f db/structure.sql epets_test" end
That way, if you want to build the services you can just do this:
docker-compose up -d docker-compose exec app ./bin/docker-setup
Taking this approach makes everything easier to reproduce. Any developer can use this configuration to spin up a few virtual machines. It doesn't matter if their machines are running Windows; Linux; or Mac.
During the workshop, the biggest blocker we had was download speed. It took between 10 and 20 minutes to get everything set up. The two steps that took the most time were:
- Downloading and installing Docker
- Building the images for the first time
Once that was done, the process went smoothly. We got to calculate test coverage; setup dual booting; run our test suite with two different versions of Rails; and fix a bunch of problems related to the jump from Rails 4 to 5.
If you are interested in applying these steps to your own application, you can check out the companion page for the Upgrade Rails 101 workshop.
The slides for my presentation are over here: Upgrade Rails 101 Workshop at Southeast Ruby '19
Are you using Docker to simplify your Rails upgrades? If not, what are you using to normalize environments in your team? I hope you found this article useful and I look forward to reading your comments below!