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
ECS stands for Elastic Container Services. Currently there are 3 ways to deploy your image to AWS ECS.
- Networking Only is the serverless way to deploy your application without having to manage servers or clusters. This is powered by Fargate
- 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.
- EC2 Windows + Networking similar to #2 but instead of Linux AMI it will create Windows OS AMI.
Getting Started
Prerequisite
- AWS Account
- AWS CLI
- RDS Postgres DB
- Elastic Container Registry (ECR) in order for us to push our image in repository
- ECS Fargate
- Create AWS Account with a user with right permissions similar to this:
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
- Create an ECR Repository via terminal.
➜ ~ 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
- Go to AWS RDS and create a database. We will be using Postgres as our production DB.
- Templates will be Free Tier just for this tutorial. Select Production if you are going to deploy production app.
- DB instance size is db.t2.micro since we selected Free Tier template
- For the remaining items just choose the default selections and create database.
- 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
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
Before I start, I would like to explain the terminologies for ECS. I was confused last time but after I read this.
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.
- 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
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
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
I’m planning to broaden up my deployment with ECS Fargate. Here are some of the future plans I have for this deployment.
- 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