Using Docker for Ruby on Rails development on Windows


Ruby on Rails development on Windows using Docker.


Tested with Windows 10.

TL;DR
For impatiens: Docker configs are available at GitHub: https://github.com/sheroz/docker-rails


Life is an amazing teacher. The past two and half years I worked full time on a project based on Ruby language and Rails framework. It was a unique experience after having many years of C/C++ and Java development. Having a foreigner status in a new country and being thousands of kilometers away from my homeland, I had to accept a challenging offer from a very ambitious startup company and jump immediately into the magical Ruby on Rails world.


The company provided me with a MacBook Pro for day-to-day development. Ruby development on macOS is great! But, I am historically tied with Microsoft OS at home, starting with MS-DOS in my youth and the latest Windows nowadays. I always used my home PC to make small changes, urgent hotfixes, or to prove new ideas.


People may think that software developers work only for a fixed time when they are in the office in front of their computers. That's not fairly true. As far as I know, when a developer is motivated and engaged, his brain works 7/24 to solve faced challenges.


Imagine that you are a Ruby on Rails developer in a startup...

It was my first experience with startups. I found that startups are a very different world. Sometimes I think that if Cervantes was alive, maybe he would re-write his famous romance about Don Quixote according to the adventures of the heroes of our time, who decided to become modern knights-errant at startups.
Ruby on Rails development on Windows using Docker. Ruby on Rails developer in a startup

You are finally at home after long hours (or days) of office rush with tight deadlines, endless meetings, calls, and other distractions...

I believe that software engineering is an art and science. The relationship between creativity and stress is a complex subject. Normally, quality and creativeness are the opposite of rush, stress, and distractions. Furthermore, software engineering is a hard and mentally exhausting process. While pushing developers gives an imaginary gain in productivity in the short-term, the product developed under high pressure probably would include baked-in time bombs.


So, you are at home and while you drink a cup of tea (or coffee) with your loved ones in a warm atmosphere, this creative moment probably will be caught by your relaxed and happy brain that will start to remember and analyze unsolved challenges in the background, and... suddenly, you see the bright solution to the interesting challenge that you had no single chance to overcome at the office. You are eager to convert the idea into code, but... unfortunately, you left your work laptop in the office (Due to the terrible traffic, of course. No laptop can survive if you carry it daily in over-crowded Istanbul traffic) and you have only your Windows PC that seems completely useless in front of Ruby on Rails... That is because setting up the Ruby on Rails development environment is not so straightforward on Windows, while it is native on Linux and macOS.

I found some workarounds for doing RoR development on Windows, using:


  1. RailsInstaller (RubyInstaller for Windows)
  2. Windows Subsystem for Linux (WSL)
  3. VM tools (like VMWare, VirtualBox, Vagrant)
  4. Docker

Or, you can make the PC dual-bootable and use Linux for the development. This is the best option if you are going to use the PC primarily for RoR development.

I tried (1) and (2) options. It works and may be usable in small projects. But, in the case of a complex RoR project, the performance was absolutely not acceptable for doing any real development.


I did not try to use VM-based solutions. I know that VM would work and overall performance would be acceptable. But I think, the Docker-based solution is more promising and flexible. It can make the setup process of the development environment easier and be used as a part of IaC solution to automate the installation process. Furthermore, I was already using Docker for the integration tests for the same project. So, I decided to give it a try and after doing some digging with Docker it worked well.


General architecture and Docker configuraion

Application consists of the following components:


  • AngularJS based Front-end managed by Bower package manager
  • REST API Back-end powered by Ruby On Rails
  • MongoDB and PostgreSQL databases
  • Redis based in-memory key-value storage

Other tools and frameworks:


  • RSpec - API and Selenium based end-to-end tests
  • Sidekiq - background processing and job scheduling
  • Capistrano - remote server automation and deployment

Codebase is hosted on GitHub in private repository.

Step by step I built and configured Docker images, containers, and wired services to cover all the requirements above.

Docker configuration is available at GitHub: https://github.com/sheroz/docker-rails


Ruby on Rails container

The app (Ruby on Rails) container is based on Linux Ubuntu 18.0.4 (bionic) image to ensure that it would work equally the same way both in development and production.


Since I use Docker, I decided to compile Ruby from the source as there is no real need to use the version managers like RVM or rbenv. Ruby version can be upgraded/set in .env parameters. After changing Ruby version the app image should be rebuilt.


To achieve better performance, I had to duplicate the source folder in the app container, as directly accessing files from the host mounted volume was very slow on Windows. (Seems the volume 'cached' option can speed up mounted volume access for macOS-based hosts, but this option does not work for Windows-based hosts yet.)


To synchronize host and in-container sources, I am using the File Watchers plugin on RubyMine IDE (finally, after having tried many other different options like unison, lsyncd, ...).


Network settings for the database and redis services

Rails application was configured to access the database and redis services on the same localhost (127.0.0.1) and this requirement is achieved by using network_mode: "service:[service name]" option.


Running services and available tools

The app container runs in user mode and sudo command is availabe without password prompt.

As a back-end developer, I start rails server in bash console what allows me to debug Ruby code by using binding.pry and see the logs. Front-end developers can configure it to start by default.

The app image has bunch of tools, including mc (The Midnight Commander, my favorite file manager).

A separate bash console can be used to start sidekiq service, capistrano and rspec tasks.


Docker Engine configuration to enable connection from RubyMine IDE

In the General section of your Docker settings, turn on the Expose daemon on tcp://localhost:2375 without TLS option.


RubyMin IDE configuration

https://www.jetbrains.com/help/ruby/settings-docker-tools.html


File Watchers plugin configuration for RubyMine IDE


Ruby on Rails development on Windows using Docker. File Watchers plugin configuration

Performance

Ruby on Rails development performance using Docker on Windows is approximately the same as development on native macOS (MacBook Pro 15, 2018) when using comparable hardware components (CPU, RAM, SSD).