Setting up a new Rails project without having ruby/rails on your system.
Tags: ruby, rails, docker
Published: 2019-08-07 21:59:17

---
title: Setting up a new Rails project without having ruby/rails on your system.
published: true
description: Introduction to Docker
tags: ruby,rails,docker
---

There are many articles on the internet about *setting up a rails app with docker*. You might be wondering, "why write another one?". I asked myself the same question. The reason I went ahead to do it is because as I learned how to use Docker, I tried to set up a rails app in it. Most of the resources I came across were using Docker Compose. That didn't help me with practising Docker very much because I wanted to be able to write those long docker commands and follow exactly what happens in that `docker-compose.yml` file. I write this article for me and anyone who might have the same need. In case you get stuck on the quest, you might pick up a cent or two from here. Let's dive into it!

1. Create the directory where you will be working from and `cd` into the 
   directory. I am going to name the app `dockerapp`.

        mkdir dockerapp && cd $_

2. Then create the initial files.
   
        touch {Gemfile,Dockerfile}

3. In the `Gemfile`, put in the code below.


        source 'https://rubygems.org'

        gem 'rails', '~> 5.2'

4. In the `Dockerfile`

        FROM ruby:2.6-alpine

        RUN apk update -qq && apk add --update alpine-sdk postgresql-dev nodejs yarn tzdata

        RUN mkdir /app WORKDIR /app

        COPY Gemfile Gemfile

        RUN bundle install

        COPY . .

        LABEL maintainer="Lorna Tumuhairwe <lornatumuhairwe@gmail.com>" version="1.0"

        EXPOSE 3000

        CMD rails s --port=3000 -b='0.0.0.0'

5. Build the image. 

        docker image build -t dockerapp .

6. Now your image has both ruby and rails installed. So we now use 
   the installed rails to generate a new rails project.


        docker container run -it -v ${PWD}:/app dockerapp rails new . --database=postgresql -f -T

7. At this point you should have the rails app in the folder since you 
   mounted the volume with `-v ${PWD}:/app`. Update the 
   `config/database.yml` file to contain the code below. I have made 
   changes to the `hostname`, `username` and `database` names to match 
   the postgres name we are going to use when we run the postgresql 
   container and the application name respectively. 


        default: &default
          adapter: postgresql
          encoding: unicode
          host: postgres
          username: postgres
          pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

        development:
          <<: *default
          database: dockerapp_development

        test:
          <<: *default
          database: dockerapp_test

        production:
          <<: *default
          database: dockerapp_production
          username: app
          password: <%= ENV['APP_DATABASE_PASSWORD'] %>

8. Rebuild your docker image since the Gemfile has changed. 

        docker image build -t dockerapp .

9. Create a network that you'll use to connect the app container and the 
   postgres container. 

        docker network create dockerapp-network

10. Run a postgresql container with the command below. Even if you don't 
    have it pulled already, it will be downloaded and used. 

         docker container run -it --rm -v pgdata:/var/lib/postgresql/data --name postgres --net dockerapp-network -p 5432:5432 postgres:9.6-alpine

11. Run the app as well in the same network. 

         docker container run --rm -it -v ${PWD}:/app -p 3000:3000 --name dockerapp --net dockerapp-network dockerapp

12. Open another terminal and create the database.

         docker exec dockerapp rails db:create

13. In your browser visit `localhost:3000`, you should be on the rails 
    welcome page!

You might have already noticed, you always have to run two long commands to run your application (step 10 and 11). But to do all that in one command, you can use Docker compose. 

#### Docker compose to the rescue. 

Create a docker-compose.yml file. 

    version: '3'
    services:
      postgres:
        image: postgres:9.6-alpine
        volumes:
          - ./tmp/db:/var/lib/postgresql/data
      dockerapp:
        build: .
        command: bundle exec rails s -p 3000 -b '0.0.0.0'
        volumes:
          - .:/app
        ports:
          - "3000:3000"
        depends_on:
          - postgres

To follow from the above, make sure your containers are all stopped. By running,
   
     docker container stop dockerapp postgres


In the same directory, run your app with 


     docker-compose up

This will run both the postgresql and application image at the same time. In case you run into any problems with the dockerapp container exiting, please ensure you don't have a server.pid file in `temp/pids/server.pid`. That's a rails specific issue that can be resolved by deleting the file. Or you can write a script to always delete it if it exists when the app is started. That's well documented in the [docker documentation](https://docs.docker.com/compose/rails/).

Thank you for reading! 
*The steps outlined in this article are only tested on a MacOS.*

*On a light note, this is my first post on the platform, I have learned a lot being here, I glad to share what I have learned as well. I hope it helps someone. :heart:*