Building Microservices with Docker and the Rails API gem
Why Choose Docker + Rails API ?
At the company that I work for, we have been using Docker to have consistent development environments for all of our engineers. This makes onboarding a new engineer a piece of cake. I’m still particularly new to Docker and want to share my experience just getting a basic Rails API application setup as a microservice. Like most companies that struggle over the long run with a monolithic Rails app, a microservice architecture provides loose coupling, strong cohesion, independent deploys, and much more.
I’ve built quite a few applications where we’ve used Rails as an API, which is a little overkill since you don’t need all the view logic and additional middleware. Instead, we’ll be using the Rails API gem to build out our microservice APIs. The Rails API gem is integrated into the Rails 5 release, which is currently in beta. I’ve explored this option using Docker, but struggled with setting it up so I’ll be writing about using a Rails 4 setup and adding the rails-api gem as a dependency to the Gemfile.
You may ask yourself why use Rails API as the tech stack for your microservice. I think the answer lies on what works best for your team. There are plenty of talks on the internet about whether or not your team should move towards microservices and what technology to use. There are a ton of other great technologies where using Node.js, Go, Scala, or Java might fit your situation. I’ve spent some time exploring some of these options and I think they are all great, but my team knows Rails the best and we can develop quickly with it. If I were to pick another tech stack that would fit well with my team, I would go with Node.js since a lot of our new apps are being built with it. I think the overall goal is to make sure your services are small enough to be rewritten if needed.
Lets start with Docker
My biggest recommendation, if this is your first time using Docker, is to go through the tutorial and installation at https://docs.docker.com/mac/ (I’m using a mac, but there are tutorials for all the platforms). Next, go through the Rails tutorial setup on the Docker website https://docs.docker.com/compose/rails/ . This will give you the fundamentals to understand how Docker works and setting up a container to run a Rails app with Postgres.
This tutorial is for Mac users, but you can adopt it for a Linux distribution or figure out the equivalent on a Windows platform. First create the directory for your project within the terminal. I’ll be making a project called “inventory manager”, but you can name your project whatever.
mkdir inventory_manager && cd inventory_manager
Then create a few files within the root directory of the project.
touch Dockerfile docker-compose.yml Gemfile Gemfile.lock
Setting up the Dockerfile
The Dockerfile is everything we need to set up our Docker container’s environment.
RUN apt-get update -qq && apt-get install -y build-essential libmysqlclient-dev
RUN mkdir /inventory_manager
ADD Gemfile /inventory_manager/Gemfile
ADD Gemfile.lock /inventory_manager/Gemfile.lock
RUN bundle install
ADD . /inventory_manager
So what is happening in this file? Here we are creating an image using the latest version of Ruby (2.3.0) at the time of this writing from https://hub.docker.com/. We then run the following apt package manager commands on the container. We’ll be using the MySQL client library for development. We’ll then add the local Gemfile and Gemfile.lock to our container’s filesystem and then install the dependencies. Lastly, we add all the contents of the project directory to the container.
Setting up the docker-compose.yml
We need to setup our docker-compose.yml file so that the Docker Compose tool can orchestrate the communication between our Rails API app and our MySQL container.
This configuration sets us up with a mysql container and also a container called web that builds from the Dockerfile and runs the Puma webserver on port 9292. We then link the Rails app container to the mysql container so that they can communicate to each other.
Setting up the Gemfile.
Inside the Gemfile we will add the Rails gem, the Rails API gem, the mysql client adapter, Puma web server, and the Active Model Serializers (this is for your formatted JSON responses).
Create the Docker image
Now its time to create the Docker image.
You will need to run this command to rebuild your Docker image anytime you make a change to the Gemfile or the Dockerfile . You can see that an image is created by typing:
Create the Rails API application structure
Next we’ll create the application structure by running the Rails API commands in the Docker image. In our docker-compose.yml we have named “web” as the container to run our commands against.
docker-compose run web rails-api new .
Setting up the database
Now we need to configure our database.yml file so we can start writing a migration.
The host is “db”, which is the same name we’ve defined in our docker-compose.yml file. This host’s value must match what you’ve defined as your database container in the docker-compose.yml file.
Lets test to see if our web applications runs
Now that the app structure has been built, lets run the web server to see if we can see the Rails status page.
docker-compose up web
Make sure to find your docker ip by running docker-machine ip <docker vm host> (for me this is aliased to default).
docker-machine ip default
Now that we’ve got our app running we can start development by creating data models, controllers, etc…
We can create more microservices in this manner and facilitate communication between apps using JSON over http by exposing different web server ports on the same Docker host. Another form of communicating between services is by utilizing messaging such as RabbitMQ. I’ll most likely be writing another blog post on RabbitMQ and communicating between services and how to get that setup.
I hope this post helps others as this was definitely a learning experience for me and I’m continuing to learn more and more about Docker. Feel free to comment and make any suggestions on improving the setup.
inventory_manager - Example of creating a Rails API app with Dockergithub.com
Want to know more? Hit me up at firstname.lastname@example.org