DEV Community

Cover image for Creating Rails API from scratch (with PostgreSQL and Docker)
Mykyta Didenko
Mykyta Didenko

Posted on

Creating Rails API from scratch (with PostgreSQL and Docker)

To create a Rails API app that uses a PostgresQL database and run it using Docker Compose, you will need to complete the following steps:

Must be installed ruby 3.0.x and docker

1 Install rails gem

gem install rails
Enter fullscreen mode Exit fullscreen mode

2 Create a new Rails API app by running the command

rails new my_api --api -d postgresql
Enter fullscreen mode Exit fullscreen mode

3 Check your ruby version in Gemfile. The Rails version you are using may not support the latest Ruby version. Updating the Ruby version specified in the Gemfile to '~> 3.0' allows you to use a version of Ruby that is compatible with the version of Rails you are using.

ruby '~> 3.0'
Enter fullscreen mode Exit fullscreen mode

4 Create a Dockerfile file in the root of your app with the following contents:

FROM ruby:3.0

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client

RUN mkdir /my_api
WORKDIR /my_api

COPY Gemfile /my_api/Gemfile
COPY Gemfile.lock /my_api/Gemfile.lock

RUN bundle install

COPY . /my_api

CMD ["rails", "server", "-b", "0.0.0.0"]
Enter fullscreen mode Exit fullscreen mode

The FROM instruction sets the base image for the Dockerfile, in this case ruby:3.0.

The RUN instruction runs a command in a new layer added to the image. The first RUN command updates the package lists and installs nodejs and postgresql-client packages.

The RUN command that follows creates a new directory called /my_api. The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile.

The COPY instruction copies files from the host file system to the container file system. The first COPY command copies the Gemfile and Gemfile.lock from the host to the /my_api directory in the container.

The next RUN command runs bundle install command to install the dependencies specified in the Gemfile and Gemfile.lock files.

The second COPY command copies all the files from the current directory on the host to the /my_api directory in the container.

The CMD instruction provides default command to execute when a container is created from the image. The command ["rails", "server", "-b", "0.0.0.0"] runs the rails server command with the option -b set to 0.0.0.0, which means that the server will bind to all available network interfaces.

5 Create a docker-compose.yml file in the root of your app as well. It should contain the following:

version: '3'
services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: my_api
      POSTGRES_PASSWORD: my_api
      POSTGRES_DB: my_api_development
    ports:
      - "5432:5432"
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    environment:
      POSTGRES_USER: my_api
      POSTGRES_PASSWORD: my_api
      POSTGRES_DB: my_api_development
    volumes:
      - .:/my_api
    ports:
      - "3000:3000"
    depends_on:
      - db

Enter fullscreen mode Exit fullscreen mode

The version field specifies the version of the Compose file format. In this case, it is version 3.

The services field defines all the services that make up the application. It has two services defined: db and web.

The db service uses the postgres image and sets environment variables for the PostgreSQL user, password, and database name to be used. The ports field maps the host's port 5432 to the container's port 5432, allowing access to the PostgreSQL instance running in the container.

The web service uses the build field to specify that the image should be built from the current directory (.) and the command field to specify command that will be executed when the container starts. This command removes the server.pid file and runs the rails server command with options to listen on port 3000 and bind to all available network interfaces. It also sets environment variables for the PostgreSQL user, password, and database name to be used, which should match with the db service's environment variables.

The volumes field mount the current directory on the host to the /my_api directory in the container, allowing changes made on the host to be reflected in the container.

The ports field maps the host's port 3000 to the container's port 3000, allowing access to the Rails application running in the container.

The depends_on field specifies that the web service depends on the db service. This means that Compose will ensure that the db service is running before starting the web service.

6 Update the config/database.yml file to include the necessary information to connect to your PostgresQL database.

development:
  <<: *default
  database: <%= ENV['POSTGRES_DB'] %>
  username: <%= ENV['POSTGRES_USER'] %>
  password: <%= ENV['POSTGRES_PASSWORD'] %>
  host: db
Enter fullscreen mode Exit fullscreen mode

7 Add this simple endpoint to config/routes.rb

Rails.application.routes.draw do
  get '/status', to: 'status#index'
end
Enter fullscreen mode Exit fullscreen mode

8 Create a controller status_controller.rb in app/controllers with this content

class StatusController < ApplicationController
  def index
    render json: {status: 'OK'}
  end
end
Enter fullscreen mode Exit fullscreen mode

Run docker-compose build to build the images for your app and database
Run docker-compose up to start your app and database.

Check the first API endpoint in your Rails app:

the first API endpoint in your Rails app

Latest comments (0)