Docker 101: Installation, Setting Up and Running Ruby on Rails Application

iRonin IT Team - Experts in software development
devops, docker, infrastructure

In this guide we run through how to install Docker, set everything up for easy configuration in the future, and run Ruby on Rails web application smoothly. Includes all code snippets required!

Remember Docker? The Quick and Easy Alternative to Virtualization for Developers and Non-Developers Alike we covered in our previous blog post? For those unfamiliar with the subject, Docker is a containerization management tool that can help with isolated development and deployment of software on any machine with any configuration, offering a clever, resource efficient alternative to spinning up traditional virtual machines. Docker allows for portable software development that can benefit all project stakeholders, including developers, managers, devops, and even customers, since Docker ensures all containers have the same configuration, independently from the host environment they are run on.

In this week’s update, we put our knowledge into practice by showing you in this Docker tutorial - creating isolated development environments, learning to setup Docker from the very beginning with a fresh Docker install, through to your first Docker run with your web application.

Installing Docker on Mac

Did you know that Docker was created with Linux namespaces in mind - that it even used LXC in its early days? What this means is that won’t run natively on OS X or Windows.

Docker for Mac (official version)

Even though there are Docker for Mac and Docker for Windows official versions, these both run Linux Alpine in a Virtual Machine (VM) under the hood, which effectively works as a Docker host VM, and they aren’t ideal for the following reasons:

  • Slow file sharing from host to container - the built in mechanism for file sharing is slower than the default Virtual Box solution, however Docker developers are working very hard to improve this situation (this GitHub issue is the best place to keep up to date on the situation)
  • The VM disk image has memory issues resulting in it taking up way too much space - by default it uses 50GB as a sparse image. For every file created, it eats up disk space - meaning, for example, if you keep creating and deleting Docker images of 2GB, it will take up 2GB, then 4GB, then 6GB… up to 50GB. Even if you remove the Docker image, it won’t give the space back to the host - plus if you reset the disk image to free up space you’ll lose your Docker images and volumes! You can check the GitHub issue here.

docker-machine with xhyve

An alternative to the official Docker for Mac solution which partially combats these issues is using docker-machine with VirtualBox (or possibly Parallels, VMware or xhyve) to install Docker. nfs file sharing is easily fixed here & there’s a disk image size trick to use with VirtualBox. We have used docker-machine with the xhyve driver in the past, however we had problems with upgrades (from time to time docker-machine didn’t want to boot for unknown reason) and file permission issues (we had to create a user with id 501 and group with id 21 to match the Mac user; the issue is that, in Linux, a group with id 21 is already reserved for dialout group to allow access to the serial ports via files in /dev).

Docker for Mac with nfs file sharing

For this reason, we switched to Docker for Mac with nfs file sharing. This handy install gives the same performance as the xhyve driver configuration. Unfortunately, this required us to simply accept the known VM disk image space issue mentioned earlier, even though our file sharing issue is addressed.

3 tips for choosing which Mac installation is best for you:

  • If you plan to run a couple of Docker VMs, then go with docker-machine, as Docker for Mac can only run a single VM under the hood.
  • Keep in mind that if you use Docker for Mac you also get docker-compose (“a tool for defining and running multi-container Docker applications”) in the package.
  • If you want to leverage the full power of Docker then you may like to use Linux since Docker was built for Linux - which we will cover in the next section.

Installing Docker on Linux

Docker was designed to run on Linux, so installation on this OS is trivial. Head over to the official installation instructions for Docker for Ubuntu to set yourself up. That’s it, really.

Preparing your application for iso(lation)

This section assumes that you already have a Ruby on Rails web application that you would like to containerize.

Docker setup

We will start off with a basic Dockerfile that should be sufficient for most Ruby on Rails web apps:


# Base image
FROM ruby:2.4.0-slim

# Install project dependencies
RUN apt-get update -qq && \
    apt-get install -y --no-install-recommends \
                        gcc \
                        g++ \
                        make \
                        patch \
                        git \
                        ssh \
                        libpq-dev \
                        postgresql-client-9.5 \
                        pkg-config \
                        ruby-dev \
                        zlib1g-dev \

# Add Postgres repo
RUN echo 'deb jessie-pgdg main' >> /etc/apt/sources.list.d/pgdg.list && \
    curl | apt-key add -

# Install Postgres client 9.5
RUN apt-get update -qq && \
    apt-get install -y --no-install-recommends postgresql-client-9.5

# Ensure we don't check host for when cloning gem repos
RUN mkdir /root/.ssh && \
    chmod 700 /root/.ssh && \
    echo "Host\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config

# Create working directory
RUN mkdir /app
# and switch there

# Config for bundle
ENV BUNDLE_APP_CONFIG=/app/.bundle \
    BUNDLE_GEMFILE=/app/Gemfile \

# Add our app files to the image
ADD . /app

# Install gems
bundle install

Even though we run bundle install in our Dockerfile (just in case we would like to provide a complete app image to someone eg. designer or copywriter), we will also keep gem files locally and mount them on run.

Gems are kept locally for 2 reasons:

  • ability to browse a gem’s code using a text editor on the host machine
  • installing new gems won’t require us to rebuild the whole image

docker-compose setup

We also need to provide info about our stack for docker-compose, which is used for orchestrating the whole application stack:

version: '2'
    image: myapp
      - .:/app
      - postgres
      - redis
      - "3000"
    command: bundle exec rails s -b
    image: myapp
      - .:/app
      - postgres
      - redis
    command: bundle exec sidekiq
    image: postgres:9.5
      - "5432"
      - postgres-data:/var/lib/postgres
    image: redis:latest
      - redis-data:/data

    driver: local
    driver: local

We use and files to emphasize that they have been created for development purposes.

nginx-proxy setup

We also run nginx-proxy in another Docker container, for easy mapping between local domains and different Docker web applications. It works automatically - if we point to localhost (for docker-machine you need to use docker-machine ip), in the /etc/hosts file, then we will be able to access the app in the browser under this name. This is thanks to the VIRTUAL_HOST environment variable in the docker-compose file.

Running nginx-proxy is as simple as this: docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

As luck would have it, it’s basically a fire and forget command. The container will be started automatically, every time your start Docker app / daemon.

Getting things up and running

Ok, now we need to build our app image:

docker build -f -t myapp .

After that we can install gems for our app (locally):

docker-compose -f run web bundle install

When it’s finished, we can start the whole stack:

docker-compose -f up

When we update our code locally (using an editor on the host machine), changes will be propagated automatically thanks to local volume mapping (.:/app).

Helpful aliases for Docker

Typing docker-compose... every time we do things is cumbersome, even with tab complete from the command line (as it cycles through docker tools). We like to instead have a few bash aliases and functions to help work with Docker’ised apps:

# Aliases

# Docker
alias dbd=docker-build
alias drun=docker-compose-run
alias dup="docker-compose -f up --remove-orphans"
alias ddown="docker-compose -f stop"
alias dcl=docker-cleanup

# Docker & bundler
alias dbi="drun bundle install"
alias dbe="drun bundle exec"
alias dbet="drun -e RAILS_ENV=test bundle exec"

# Functions

# Build docker image
# docker-build $image-name
docker-build() {

  docker build -f -t ${project_name} .

# Cleanup stopped container and unused images
docker-cleanup() {
  docker ps -a | grep "Exit\|Created" | awk '{print $1}' | xargs docker rm
  docker images | grep "none" | awk '{print $3}' | xargs docker rmi

# Run command against docker web container defined in
# file.
# Pass -u argument to run as user with current user id
# Pass -e arguments for env variables, ie:
#   docker-compose-run -e RAILS_ENV test bundle exec rake db:migrate
docker-compose-run() {

  # Parse -e options
  while [[ $# > 0 ]]
  case $i in
      var="${var} -e $2"
      var="${var} -u $(id -u)"
      cmd="${cmd} $1"

  # Trim whitespaces
  cmd=echo "${cmd}" | sed 's/^ *//' | sed 's/ *$//'
  var=echo "${var}" | sed 's/^ *//' | sed 's/ *$//'

  cmd="docker-compose -f run --service-ports --rm ${var} web ${cmd}"
  echo "Running: ${cmd}"
  eval $cmd

With all these helpers configured, your Docker workflow can look as simple as this:

  • dbi - install all gems
  • dup - start whole stack
  • dbe rspec - run all rspec tests
  • dbe rake db:migrate - migrate the database
  • dbe rake db:drop db:create db:migrate - re-create database for test environment (btw. this could also be done with aliases!)
  • ddown - stop the whole stack (in case of errors occurring)
  • dcl - to clean stopped containers and unused images


We love Docker! We use it during the whole web app development cycle: from development to running the app on production servers. Want to leverage Docker for your app development or existing infrastructure? iRonin team are experts in setting up Docker and guiding businesses through how to use it effectively. If you’d like to incorporate Docker into your development cycle then make sure to reach out and have a chat with us - we’re always happy to help.

Author's Bio
iRonin IT Team

Experts in software development

We are a 100% remote team of software development experts, providing web & mobile application development and DevOps services for international clients.

Similar articles

Bulletproof your development with remote team augmentation

Read how
This page is best viewed in portrait mode
Our websites and web services use cookies. We use cookies and collected data to enhance your experience, provide additional communication channels, improve marketing materials and enhance our offer. IRONIN SP. Z O.O. SP. K. is committed to protecting all the data that we collect or process in any way, especially data of personal nature. By accepting these terms you agree to our usage of cookies and processing your data, according to our Privacy Policy, and you declare that your browser settings reflect your preferences. Read more You have the right to revoke this agreement at any time, based on the terms of our Privacy Policy. You can change cookies settings in your browser. If you do not agree with us using cookies and processing your data, please change your cookies settings in your web browser and reject these terms. You can find more information about cookies, your data privacy This site uses cookies. By continuing to browse the site, you are agreeing to our use of cookies. data processing, and your rights in our Privacy Policy.