A while ago, an ‘OS X native’ version of Docker was released in beta stage. Thinking that it would be a better experience than my previous, I decided to give it a go. Here are my findings.

Introduction

The past February I published a blog post in which I commented on my experience in making an existing Rails application work under Docker. Since then, many things have changed, mostly Docker Beta for OS X being released. My main worry while working with Docker under VirtualBox was its slower speed compared to The Real Thing (TM), so having it running natively seemed like a powerful enough reason to try again.

The first thing would be getting access to the private beta, so I enrolled and after a few days, I had a shiny invitation in my inbox.

After signing up, I cleaned up my current Docker installation (which had around 20GB of disk space in use), by following the instructions I found in several places on the internet:

Once everything is squeaky clean, we’re ready to install the Docker Beta. While it was getting installed, I kept reading the docs to find out if this new version still uses virtualization, but a lightweight solution. In any case, I still hoped there would be a gain in switching.

Putting your good advice to work

On my previous blog post about Docker I received some helpful comments on how to write out my files in order to get a faster build and a cleaner environment (thank you Roman!). So I ended up with a Dockerfile like this one:

FROM ruby:2.2.1
MAINTAINER Julio Antequera Galiano <julio@cookieshq.co.uk>

RUN apt-get update && apt-get install -y \
    build-essential \
    libqt5webkit5-dev \
    nodejs \
    qt5-default \
    xvfb

ENV app /app
RUN mkdir $app
WORKDIR $app
RUN gem install bundler -v 1.10.0
ENV BUNDLE_PATH /bundle

WORKDIR $app
COPY . ./

And this docker-compose.yml, using version 2 of the docker-compose syntax:

version: '2'

services:
  db:
    image: postgres:9.4
    ports:
      - "5432"

  mailcatcher:
    image: schickling/mailcatcher
    ports:
      - "1080:1080"
      - "1025:1025"

  app:
    build: .
    command: ./script/start.sh
    volumes:
      - .:/app
      - bundle:/bundle
    ports:
      - "3000:3000"

volumes:
  bundle: {}

And my app start script:

#!/bin/bash

bundle check || bundle

if ! gem list foreman -i
then
  gem install foreman
fi

foreman start -p 3000

As I learned in the documentation and by other comments, this new syntax allowed us to drop the links directives because services would discover each other automatically by service-name.

So with this change, I gained the ability to use mailcatcher as a service instead of as an installed gem on my application image. For some reason I couldn’t get it to run on my previous experimentation with Docker, so this is definitely a plus.

Also I got to keep my gems bundled in an independent volume so building my app image wouldn’t need to download the whole Internet each time.

Trying things out

I had my app working in no time, and it surprised me that I had to go to localhost:3000 to see my app running, instead of docker.local or some other IP address, as I had to do in the past. Something was doing magic in the background to make the experience more seamless and it was good at it.

Anyway, I noticed the overhead on each docker-compose run call was still slower than what I would be comfortable with (notice I’m running a 2011 MacBook Pro with 16GB of RAM and an SSD HDD).

Running docker-compose run --rm app bundle exec rake would take approximately:

Finished in 1 minute 59.44 seconds (files took 34.48 seconds to load)
711 examples, 0 failures, 1 pending

While doing this in my usual environment would take almost a minute less. Still slow to my liking, to be honest.

Anyway, after the application preloading in Puma, browsing in developement mode was comfortable enough, so maybe if I had Guard running, the time it took to run the tests would be less of a problem…

Guard WORKS!

Last time I couldn’t get Guard to work, mostly because I didn’t want to go to hell and back to have my Docker-Toolbox installation watch after my real filesystem (where I did the changes that would trigger Guard).

Anyway, this time I loaded Guard by running (docker-compose run --rm app bundle exec guard) and after it loaded I hit enterERRROR.

Turns out the active_admin version I was using had some trouble, so I updated it to the latest version and tried again… and it worked! Still over two minutes to run all the specs, but we’re making good progress. Finally the communication between my real filesystem and the docker image is working perfectly.

Next test was editing a Ruby file in my editor and seeing if it triggered Guard. Removing a validation on a model and Guard picked it up almost instantly, although it took a painful amount of time to run the three tests the model had. All in all, not fast enough.

Guard Livereload

My last test was trying to get guard-livereload to work, and I have failed to do so. When I try to connect using the Chrome extension, I get an alert saying that there’s no livereload server active, although I see Guard is waiting for a browser to connect and when I change a haml file it sends back the order to reload.

I’m guessing that maybe I need to expose another port under the app section in my docker-compose file, or I need to configure the host and port options in the livereload section of my Guardfile, but I still haven’t found some general explanation/solution that goes beyond “I tried X and Y and it magically worked for me”. Anyway, I’m too used to Cmd+R, so I can live without livereload, to be honest.

Conclusions

I must recognize I was a bit hyped about the ‘fakely-native’ Docker for OS X, and finding it was still not fast enough on my machine let me down a bit. But on the other hand, it’s faster than before and I got things like Guard and Mailcatcher working out of the box, so I’d say Docker has made a great progress, being now on the good path to accommodate the everyday development needs and it will get there eventually.

As a side note, a possible problem for newcomers is the amount of Docker tutorials and docs out there on the Internet that are already outdated/wrong-in-some-way. I guess it’s normal for such a ‘new’ and fast-changing systems software, but it might be a turndown nonetheless.

Read my first post about Docker here.

Picture ‘Fly, my little Whale friend, fly!’ by Christopher Michel, used under CC BY 2.0 license.