My personal experience Dockerizing a Ruby on Rails Application: Deploy to AWS ECR using Github Actions

Adetokunbo Ige
6 min readAug 19, 2024

--

I recently received a request on how to Dockerize a Ruby on Rails application after a user reviewed the article I wrote on Dockerizing a Rust Application. Containerizing a Ruby on Rails application enhances scalability, consistency, and dependency isolation across environments, while also improving deployment efficiency, making it an essential tool for modern development practices.

Ruby on Rails is a reliable and powerful framework for developing web applications, boasting a rich ecosystem and strong community support. The combination of Ruby on Rails and Docker allows developers, to build, deploy and scale web application with enhanced speed and reliability.

Docker ensures that your application runs consistently across all the environments, it eliminates the popular statements from developers. “The application works on my system, i am not sure why it is not working on your system or i am not sure why it is not working on production.”

Setting up Ruby on Rails and Docker provides a solid foundation for building and deploying web applications. Rails offers a powerful framework for development, while Docker ensures your applications run consistently across all environments. Together, they create a streamlined and efficient workflow for modern web development.

This article shows how to Dockerize your first application in Ruby on Rails and deploy this application to AWS ECR. This is an assumption that you already have an understanding of AWS ECR and GitHub Actions.

Below is a step-by-step guide on how to Dockerize an application in Ruby on Rails and deploy this application to AWS ECR.

Step 1: Setting Up Your Environment: Install Ruby on Rails, Docker and Docker-Compose

Ruby on Rails requires Ruby to be installed first. You need to have Ruby, Docker Compose and Docker running in your development environment if you do not already have it running.

  • Ruby: Install Ruby follow this link, it explains how to install Ruby on different Operating systems or environments.
  • Docker: Install Docker and Docker Compose, follow this link, it describes how to install Docker on different Operating System. Next steps will be to install Rails once you have successfully installed Ruby.

Use the command below to install Rails.

gem install rails

To verify the installation of Rails.

rails -v

Step 2: Setting Up the Project. Todo App on Ruby on Rails

Next, create a New Rails application which will be Todo App. Run the following command below.

rails new todo-app -d postgresql
cd todo-app

After running the command a folder called todo-app will be created which will contain the Rails code. Also, the -d postgresql flag will set PostgreSQL as the default database.

Step 3: Set Up the Database Configuration

After running the command with the flag above, the database configuration will be created in this location config/database.yml which will contain information about the database connection string.

default: &default
adapter: postgresql
encoding: unicode
host: <%= ENV['DATABASE_HOST'] %>
username: <%= ENV['DATABASE_USER'] %>
password: <%= ENV['DATABASE_PASSWORD'] %>
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
<<: *default
database: todo_app_development

test:
<<: *default
database: todo_app_test

production:
<<: *default
database: todo_app_production

Step 4: Install Gems

Run the command below to install all the required gems.

bundle install

Step 5: Generate the Todo Scaffold

Generate a basic scaffold code for the Todo app with the command below

rails generate scaffold Todo title:string completed:boolean

Step 6: Create the Dockerfile

In order to containerize the Ruby on Rails Application, you need to create a Dockerfile . Create a new file on the root directory of your project with filename, Dockerfile which will contain instructions on how to build the Docker image of your application.

Open the newly created file Dockerfile and copy and paste the code below in the file.

Please note: From Ruby version 7.1 by default comes with Dockerfile and docker ignore files out of the box. But for simplicity case, i am creating my own Dockerfile as an example for this article.

# Base image
# Base image
FROM ruby:3.2.2

# Set the working directory
WORKDIR /app

# Install dependencies
RUN apt-get update -qq && \
apt-get install -y nodejs postgresql-client && \
rm -rf /var/lib/apt/lists/*

# Set development environment
ENV RAILS_ENV="development" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="production"

# Install application gems
COPY Gemfile Gemfile.lock ./
RUN bundle install

# Copy the application code
COPY . /app

# Expose the port the app runs on
EXPOSE 3000

# Start the Rails server
CMD ["rails", "server", "-b", "0.0.0.0"]

Step 7: Create a .dockerignore File

In order to prevent unnecessary files from being added to your Docker image, create a new file in the root directory with filename dockerignore . By adding the .dockerignore file this will reduce the size of the docker image and only ensure that we have only the necessary files.

Open the newly created file .dockerignoreand copy and paste the code below in the file. You can add more file that you will like to ignore, this is just an example.

# See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files.

# Ignore git directory.
/.git/
/.gitignore

# Ignore bundler config.
/.bundle

# Ignore all environment files (except templates).
/.env*
!/.env*.erb

# Ignore all default key files.
/config/master.key
/config/credentials/*.key

Step 8: Set Up Docker Compose

Using Docker Compose will simplify the process of running the Ruby on Rails application and it’s dependencies such as the PostgreSQL database. This will allow you to conveniently parse the database connection string.

Create a file with the filenamedocker-compose.yml on the root directory. Copy and paste the code below in the newly created docker-compose.yml file. The docker-compose.yml file will setup the database schema.

version: '3.8'
services:
db:
image: postgres:13
volumes:
- db_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
POSTGRES_USER: postgres
POSTGRES_DB: todo_app_development

web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bin/rails db:create db:migrate && bin/rails server -b 0.0.0.0"
volumes:
- .:/rails
ports:
- "3000:3000"
depends_on:
- db
environment:
DATABASE_HOST: db
DATABASE_USER: postgres
DATABASE_PASSWORD: password
DATABASE_NAME: todo_app_development

volumes:
db_data:

Step 9: Run the Ruby on Rails Application with Docker Compose

The command below will build the Docker image, start the PostgreSQL database and run the Rails server.

docker-compose up

You can access the Ruby on Rails application from your favorite browser at http://127.0.0.1:3000/

Step 10: View the ToDo’s App

In order to view the ToDo’s App endpoint. Open your favorite web browser and go to http://127.0.0.1:3000/todos to see your Todo application in action.

Follow this Step to Deploy Docker Image to AWS ECR from your workstation

Step 1: Authenticate with AWS

Before pushing your Docker image to Amazon ECR, you must authenticate with AWS services using either IAM roles or AWS access keys and secret keys.

Step 2: Create AWS ECR Repository to deploy Docker image to AWS ECR

You will need to create a AWS ECR Repository. Use the command below to create the repository. Replace <your_account_id>.dkr.ecr.us-east-1.amazonaws.com with your newly created Amazon ECR URI

aws ecr create-repository --repository-name ruby_on_rails_docker_guide
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin <your_account_id>.dkr.ecr.us-east-1.amazonaws.com

Step 3: Push Docker Image to Amazon ECR

The next step is to push the docker image you built locally to AWS ECR. See the command below on how to achieve this. Replace <your_account_id> with your AWS Account.

docker tag ruby_on_rails_docker_guide:v0.0.1 <your_account_id>.dkr.ecr.us-east-1.amazonaws.com/ruby_on_rails_docker_guide:v0.0.1
docker push <your_account_id>.dkr.ecr.us-east-1.amazonaws.com/ruby_on_rails_docker_guide:v0.0.1

Follow this Step to Deploy Docker Image to AWS ECR using GitHub Actions

Step 1: Authenticate with AWS for GitHub Actions

Before pushing your Docker image to Amazon ECR using GitHub Actions, you must authenticate with AWS services using either IAM roles or AWS access keys and secret keys. But i prefer to use IAM roles to authenticate with AWS. Using IAM roles for AWS authentication enhances security by providing temporary, least-privilege access and eliminates the need for hardcoded credentials.

To use IAM roles in GitHub Actions, you can set up OpenID Connect (OIDC) authentication. This approach allows GitHub Actions to obtain temporary credentials from AWS based on the IAM role associated with the GitHub workflow.

Step 2: Add AWS IAM Role, AWS ECR and AWS Region to GitHub Secrets

Add the AWS IAM Role ARN, AWS ECR and AWS Region to GitHub Secrets to securely configure authentication and deployment settings for your GitHub Actions workflows.

Step 3: Run the GitHub Actions pipeline

Run the GitHub Actions pipeline

Conclusion

I hope you find this process of Dockerizing Ruby on Rails Application useful and interesting. Check out the complete code on GitHub

--

--

Adetokunbo Ige

SRE, DevOps, Software dev, Enterprise App Mgt , Server Infrastructure Mgt, Cloud technologies, Database Mgt, Incident Mgt