My personal experience Dockerizing a Ruby on Rails Application: Deploy to AWS ECR using Github Actions
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 .dockerignore
and 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