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.
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:
Next, in that directory, we have to create file called `Dockerfile` with that inside:
UPDATE! Docker file for alpine image
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:
source 'https://rubygems.org' gem 'rails', '~> 5.0.2'
and empty Gemfile.lock too:
In our main directory, let’s create 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:
- Build context. It points, that we’ll be building container using data from app_name directory
- Command that we’ll be run when we will start our container
- Volumes where we defined directories shared between our local machine and container
- Ports that will be redirected from our localhost to container host
- 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:
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.
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).