DEV Community

Lorna Tumuhairwe
Lorna Tumuhairwe

Posted on • Edited on

Setting up a new Rails project without having ruby/rails on your system.

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.

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. ❤️

Top comments (0)