Loading...

Setting up Rails API with Docker

docker rails api

Lately, Docker has gotten a lot of popularity and it turns out, that there are some serious reasons behind that. It simplified containers so much, that even developers can handle managing them. When building a new application, it’s worth to consider building it in docker container.It won’t depend on your local machine and can be easily moved to your teammates’ machines.

Prerequisities

First, you need to install Docker (If you’re mac os user, I recommend to use Docker for Mac https://docs.docker.com/docker-for-mac/install/) and Docker Compose. I won’t go through installation, because I believe, that you can handle it by yourself.
You don’t need to have ruby installed on your machine. It’ll be provided in docker image.

Assuming, that you have installed Docker correctly, let’s get to some action. When you’re building API, I’m assuming you will be building some frontend too. Let’s create a directory for our applications. We’ll put applications’ directories, scripts for managing our containers and docker-compose.yml file, which is the configuration file for docker compose tool.

`mkdir app_name && cd app_name`

API Application Dockerfile

We want to have ours applications in separate directories so let’s create one:

`mkdir app_name_api`

Next, in that directory, we have to create file called `Dockerfile` with that inside:

UPDATE! Docker file for alpine image

app_name/app_name_api/Dockerfile

FROM ruby:2.4.0
RUN mkdir /app_name_api
WORKDIR /app_name_api
ADD Gemfile /app_name_api/Gemfile
ADD Gemfile.lock /app_name_api/Gemfile.lock
RUN bundle install
ADD . /app_name_api

With this Docker will:

  • Build container with ruby 2.4.0 image
  • Create directory at /app_name_api
  • Set working directory to /app_name_api
  • Copy Gemfile & Gemfile.lock files from our local machine to create a directory in the container
  • Install application dependencies
  • Add everything from current directory to directory in container

We’re missing Gemfile and Gemfile.lock at the moment, so let’s create Gemfile in app_name_api directory with this as a content:

app_name/app_name_api/Gemfile

source 'https://rubygems.org'
gem 'rails', '~> 5.0.2'

and empty Gemfile.lock too:

`touch app_name_api/Gemfile.lock`

Compose Magic

In our main directory, let’s create docker-compose.yml

app_name/docker-compose.yml

version: '2'
services:
  db:
    image: postgres
  api:
    build:
      context: ./app_name_api
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - ./app_name_api:/app_name_api
    ports:
      - "3000:3000"
    depends_on:
      - db

In the first line we defined version of docker compose. Next, we defined 2 containers: `db` which is just simple image with PostgreSQL server and `api` which is container that will store our application where we defined:

  1. Build context. It points, that we’ll be building container using data from app_name directory
  2. Command that we’ll be run when we will start our container
  3. Volumes where we defined directories shared between our local machine and container
  4. Ports that will be redirected from our localhost to container host
  5. depends_on: we tell compose build and run `db` before `api`

Back to application

Assuming that we have docker-compose.yml, Dockerfile, Gemfile and Gemfile.lock in proper directories, we can create our new api aplication running:

`docker-compose run api rails new . –force –database=postgresql –skip-bundle –api`

Short explanation: It’ll create new rails application in build context of api container that will overwrite all conflicting files(Gemfile at the moment), database set to PostgreSQL and api mode. We’re skipping bundle because it’s defined in our Dockerfile.
We didn’t need to run `bundle install` because Docker took care of it for us.

Following that, we’re just 3 steps from working application. We need to configure database connection, run containers and setup database. Remove the content of app_name_api/config/database.yml and fill it with:

app_name/app_name_api/config/database.yml

development: &default
  adapter: postgresql
  encoding: unicode
  database: app_name_api_development
  pool: 5
  username: postgres
  password:
  host: db

test:
  <<: *default
  database: app_name_api_test

We have our `db` container so we don't have to care about installing Postgres at all. We can just connect to it like that.

We're already close to working application. We just need to build our container with `docker-compose build`. We have to run it every time when we change something in Gemfile. It can take a while since bundle will install all dependencies for our app.

Now we're ready to start our containers with `docker-compose up`.

And now the last step. Let's setup database with:

`docker-compose run api rails db:create`

Finally, we can visit http://localhost:3000 and we should see familiar rails welcome page.
rails on docker

Feel free to leave comment and questions! In one of upcoming posts, I'll share with you bash scripts for easier managing our containers.
If you like it, you can follow me on twitter/facebook or subscribe to push notifications(red mark in the left down corner of the page).

5 thoughts on “Setting up Rails API with Docker

  1. Great article, I have to try this in my project.
    I have one thought, maybe you should consider adding a comment with path to file and file name at the top of every code snippet, it is very helpful despite you included it above.

    Looking forward to progress, good luck with you project!

    1. I’m really happy that you enjoyed the article. I added paths before each file content, so it’s easier now to understand it.
      Thanks!

Leave a Reply

Social media & sharing icons powered by UltimatelySocial