Deploy Rails App image in serverless way using AWS Fargate

From my previous article, I wrote about containerising a Ruby on Rails app. Now for this article my goal is to deploy this in production like AWS ECS Fargate.

Introduction to AWS ECS Fargate

  1. Networking Only is the serverless way to deploy your application without having to manage servers or clusters. This is powered by Fargate
  2. EC2 Linux + Networking is a highly scalable, high-performance container orchestration service that supports Docker containers and allows you to easily run and scale containerized applications on AWS. You will need to manage EC2.
  3. EC2 Windows + Networking similar to #2 but instead of Linux AMI it will create Windows OS AMI.

Getting Started

High level flow for our deployment on Fargate

Prerequisite

  • AWS Account
  • AWS CLI
  • RDS Postgres DB
  • Elastic Container Registry (ECR) in order for us to push our image in repository
  • ECS Fargate
  1. Create AWS Account with a user with right permissions similar to this:
It’s not necessary to have FullAccess for ECS and ECR but this to simplify this tutorial.

2. Next we will configure our AWS CLI, to do this you need to configure this via terminal using aws configure and copy paste the credentials generated for your AWS user

➜  ~ aws configure
AWS Access Key ID [****************IFZS]:
AWS Secret Access Key [****************LjSB]:
Default region name [ap-southeast-1]:
Default output format [None]:

Setting up ECR

➜  ~ aws ecr create-repository --repository-name rails_docker

The output from this will have the repostoryUri . This is to tell where to push our docker image

2. Authenticate your local machine to able to push in ECR.

➜  ~ $(aws ecr get-login --no-include-email)
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded

3. Head to your rails docker app. Build, tag and push to ECR

Build the rails_docker app using

➜  ~ docker build -t production .

Tag the version using

➜  ~ docker tag rails_docker:latest <repositoryUri-from-step-1>

Push the image to ECR

➜  ~ docker push <repositoryUri-from-step-1>

By now you should see your repository in AWS Console ECR

Setting up RDS

  1. Templates will be Free Tier just for this tutorial. Select Production if you are going to deploy production app.
  2. DB instance size is db.t2.micro since we selected Free Tier template
  3. For the remaining items just choose the default selections and create database.
  4. After the DB instance has been provisioned. Select the DB instance and copy the Endpoint under Connectivity & Security Tab.

6. Click on the VPC Security group under Connectivity & Security Tab. And change the Inbound rules of security group

Change the source to anywhere or specify the IP address from where are you going to create the DB

7. Go to your rails_docker application and under database.yml specify the production configuration

default: &defaultadapter: postgresqlencoding: unicodepool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
production: <<: *default database: <%= Rails.application.credentials.database_name %> username: <%= Rails.application.credentials.database_username %> password: <%= Rails.application.credentials.database_password %> host: <%= Rails.application.credentials.database_endpoint %> port: 5432

Credentials will be placed on credentials.yml.enc don’t forget to put the master.key in .gitignore

8. You should be able to create and migrate the DB from your local using

➜  ~ rake db:create db:migrate RAILS_ENV=production

Setting up ECS Fargate

Cluster is a logical way to group services and task definition.

Services are used to run load balancers in front of group of tasks. This is also where you specify how many instances of task should be running.

Tasks are the running instances of a task definition.

This might not be understandable as of the moment, but you will understand it on the hands on.

  1. Create a task definition under AWS ECS Console by clicking “Create new task definition”

2. Select the launch type Fargate

3. Configure the task definition

4. Under task size select the task memory (GB) in 0.5 GB and task CPU (0.25 vCPU). This still depends on your desired capacity.

5. Click Add container to specify the docker image we will be using for our task definition. In this case we will use the image we pushed earlier in ECR which is in Setting up ECR

General config for our container in Task Definition
Environment Variables

After everything is settled click Add and create task definition.

6. Go to Clusters and create click Create Cluster. Select Networking Only

  • Name your cluster e.g. rails-docker-cluster. No need to specify VPC and Tags

7. After our cluster has been created. Click rails-docker-cluster cluster and Create Services under services tab.

and click next step. .

  • configure network by adding default VPC.
  • For subnets just select one of available subnets under your region. In our case ap-southeast-1
  • Set load balancer to none
  • For auto scaling we will not specify
  • Review and create your service

10. Go to tasks tab under your cluster and Create Task

For task definition, select the task definition we created earlier.

11. After your task has been provisioned

  • Go to your cluster
  • Click Tasks tab
  • Select the created task
  • In network click ENI-Id
  • Access the IPv4 public IP in your browser. e.g http://3.0.XX.XX/
  • If there are any errors you can check the logs under tasks tab then created task.

Moving forward

  • Access rails console using ssh. This will be interesting because ECS Fargate doesn’t create EC2 since it’s serverless
  • Integration of rails docker with SQS
  • Orchestrate using AWS EKS cluster

Hope this helps to jumpstart your deployment in AWS Fargate! If got any questions feel free to message me

Full Stack Software Developer based in Singapore. Software Developer since 2012. Specialized in Ruby on Rails, Vue.js. AWS Development.