Recently I was working with a friend on their Rails app, which had been fully wrapped in a
docker-compose setup. They were quite rightly asking me questions about the best way to do things like run the server, run tests, migrate the database and other common Rails tasks. While I’ve seen a number of different ways of Dockerizing Rails in development, my preferred way is not to Dockerize my Rails app itself. In development I prefer to use Docker to manage any complex dependencies my application has, leaving my app running bare on my machine. When it comes to production time, that’s the ideal place to Dockerize your application. Let’s look at why!
It starts with the “Rails Way”
The “Rails Way” is all the stuff that Rails is designed to make really easy, for example:
- Using generators to quickly build out standard pieces of your app
- The Rails console to quickly modify development data
- Code reloading
- Being able to get in to your database if you really need to
In order to do get all the benefits of Rails’s finely honed development tools you typically need a postgres (or mysql) database, and a redis instance (because you’re using sidekiq right ;)). Those dependencies are all pretty easy to get going on a Mac or Linux machine these days. So: if I’m building a Rails app that has an eventual Docker target in production, but only those simple dependencies, it is my preference to not use Docker in development at all. This way, I get the experience of developing Rails as it is intended, and all the benefits that come with it being local to my machine.
I have my editor set up so that I can drop in to a Rails console or execute the tests with a quick flick of my hand. Those shortcuts work because the commands execute on the local machine. I’ve never found a way where I can achieve the same level of seamlessness using any combination of Docker or
But what about if my Rails app needs a constellation of microservices to be realistic
This is becoming a more common case. Let’s say that you’re a company that grew up on a Rails monolith. You’ve extracted functionality to a microservice that means you can’t realistically develop your Rails app without the extracted microservice up and running. Also, your microservices are a huge pain to coordinate without Docker and
docker-compose. You also have this case if you have a more complex dependency like Elasticsearch, or Neo4j, or some other component to your application that isn’t trivial to
brew install and have work.
So your Rails app is dependent on something that you can’t for whatever reason run cleanly bare on your machine. What I do in these cases is build a
docker-compose.yml file which knows how to spin up all my app’s dependencies, and then use
.env to point my development server running on my bare machine at those services. This way, I get all the benefits of local Rails development, and all the benefits of Docker for the things that are hard to run on my machine.
I love using Docker for Rails in production
For clarity, I do think you should still Dockerize your Rails app if you have a good production container runtime story. Containers provide you with the ability to deploy a single static artifact of your application. This artifact ensures that every server is running the exact same code, has the exact same assets, and if configured properly, is talking to the exact same dependencies. There’s a mountain of benefit there. In production, I don’t need many of those “Rails Way” things, a console, a reloader, running the tests are all not useful in that environment. It’s quick and easy to get started with Docker for Rails. It’s a very appropriate way to get your app to production.
Working with Rails for the last 10 years of my life has been an absolute joy. I want to keep using the amazing tooling that I’m familiar with. I want to get as much of the benefit as I can from Docker, and all the tooling that comes with it. In my opinion, though, Docker isn’t well suited for Rails development because the local development experience has been so thoroughly optimized. Instead: using Docker for what it’s good at which is isolating dependencies makes a tonne of sense in a traditional Rails development context. Docker is well suited to deploying Rails apps to production, however, and you should by no means take this as a dislike for the technology. Docker is great, and using it in production has genuinely made my life significantly easier. Your optimised development environment is Rails, with docker supporting, and not the other way around.