window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster already exists') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Deploying Rails app with Amazon ECS - The Codest
The Codest
  • About us
  • Services
    • Software Development
      • Frontend Development
      • Backend Development
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Data Engineers
      • Cloud Engineers
      • QA Engineers
      • Other
    • It Advisory
      • Audit & Consulting
  • Industries
    • Fintech & Banking
    • E-commerce
    • Adtech
    • Healthtech
    • Manufacturing
    • Logistics
    • Automotive
    • IOT
  • Value for
    • CEO
    • CTO
    • Delivery Manager
  • Our team
  • Case Studies
  • Know How
    • Blog
    • Meetups
    • Webinars
    • Resources
Careers Get in touch
  • About us
  • Services
    • Software Development
      • Frontend Development
      • Backend Development
    • Staff Augmentation
      • Frontend Developers
      • Backend Developers
      • Data Engineers
      • Cloud Engineers
      • QA Engineers
      • Other
    • It Advisory
      • Audit & Consulting
  • Value for
    • CEO
    • CTO
    • Delivery Manager
  • Our team
  • Case Studies
  • Know How
    • Blog
    • Meetups
    • Webinars
    • Resources
Careers Get in touch
Back arrow GO BACK
2021-11-17
Software Development

Deploying Rails app with Amazon ECS

The Codest

Marcin Doliwa

Software Engineer

In this tutorial, I’d like to show you how to deploy a sample Rails app using the Amazon Elastic Container Service (ECS).

Let’s create it by running rails new sample-rails-app, then generating a basic controller action rails g controller Welcome index and setting routes to the root path as a `root to: welcome#index”.

Our goal is to see this welcome page deployed using ECS.

Create a repository with Amazon Elastic Container Registry (ECR)

Amazon ECR is a container registry. We will be using it to store our app’s images and pull them from it so that they run on ECS.

Go to your AWS panel, look for Elastic Container
Registry
and click Get Started. You’ll see the below screen:

repository with Amazon Elastic Container Registry

We will create a private repository and name it sample-rails-app.

The repository is there, but it’s empty. We want it to contain our app’s image. This is the next step.

# throw errors if Gemfile has been modified since Gemfile.lock

RUN bundle config --global frozen 1

WORKDIR /app

COPY Gemfile Gemfile.lock ./

RUN bundle install

COPY . .

CMD ["rails", "server", "-b", "0.0.0.0"]

Then we should build an image and push it to the ECR repository.

Before that, let’s precompile assets with `rails assets:precompile`.

Now, go to the created repository. At the top of the screen, you’ll see a View push commands button with details on how to do this.

In my case (Linux), I run it with these AWS instructions:

aws ecr get-login-password --region eu-central-1 | docker login --username AWS --password-stdin 212516879399.dkr.ecr.eu-central-1.amazonaws.com

docker build -t sample-rails-app .

docker tag sample-rails-app:latest 212516879399.dkr.ecr.eu-central-1.amazonaws.com/sample-rails-app:latest

docker push 212516879399.dkr.ecr.eu-central-1.amazonaws.com/sample-rails-app:latest

Make sure that your user is permitted to do this operation. I added AmazonElasticContainerRegistryPowerUser policy to my user, which looks like this:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ecr:GetRegistryPolicy",
                "ecr:DescribeRegistry",
                "ecr:GetAuthorizationToken",
                "ecr:DeleteRegistryPolicy",
                "ecr:PutRegistryPolicy",
                "ecr:PutReplicationConfiguration"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "ecr:*",
            "Resource": "arn:aws:ecr:*:212516879399:repository/*"
        }
    ]
}

We have our docker image prepared.

Creating the Application Load Balancer

I want the outside world to be able to connect only to my Application Load Balancer. It will pass traffic to containers that are running inside our ECS cluster.

Go to EC2 services -> Load Balancing -> Load Balancers, click Create Load Balancer, select Application Load Balancer and click the Create button.

Set its name to sample-rails-app-alb, use your default VPC and select all its subnets.

We’re left with Security Groups and Listeners and routing sections.

Security Groups

We will create a new security group for our load balancer. It works like a firewall; we will set the rules for inbound and outbound traffic. We want to accept inbound http traffic (TCP port 80) and allow all outbound traffic. 

To do this, click on the “Create new security group” link.

In the section “Basic details”, set name and description, leave the default VPC.

In my case – name: “sample-rails-app-alb-sg”, description: “http from outside, all from inside”

Add the inbound rule with Type: HTTP and Source: Anywhere-IPv4. Leave outbound rules as they are.

Click create security group, then go back to the tab where you were creating the Application Load Balancer, refresh security groups and add the one we’ve just created, remove the default one.

Listeners and routing

In this section, we will define to where we want the load balancer to pass traffic. Leave Listener Protocol and Port as HTTP and 80, as this is exactly what we want, and click “Create target group” link.

Set the name to “sample-rails-app-alb-tg”. The only change is the Port number. We will be passing it to port 3000 as this is the one for our Rails app. Ignore the next step (Registered targets) and create the target group.

Now go back to the tab where we were creating the Application Load Balancer, refresh the target group and select the one we’ve just created.

We have our Application Load Balancer ready, now let’s play with ECS.

Creating an ECS Cluster

There is a lot of scary terms you’re going to see – cluster, tasks, tasks definition, services. To make it simpler, think about the cluster as a group of servers (EC2 instances). On each one, we run tasks, which are just a group of containers running together. Task definition describes which containers are in a given group and which resources we would like to give them (memory, cpu). Services keep an eye on these tasks to make sure that there is always correct number of healthy tasks running in our cluster.

With this in mind, let’s create our cluster.

Go to the ECS page and click on the Clusters link and Create Cluster button. Choose the “EC2 + Linux Networking” one and click Next Step. 

Set the cluster name to “sample-rails-app-cluster”. Choose the EC2 instance type, I took the t2-micro one as it’s available within the Free Tier plan. Leave the number of instances as 1. 

In the networking section, use your default VPC and select all its subnets. Click create, wait a little bit and voila, we have a new ECS Cluster created.

Task Definition

Click on the Task Definitions link, then Create new Task Definition button. Select the EC2 option and click Next Step. The app that we’re going to run is very simple, so we need only a few options here. 

Set Task Definition name to “sample-rails-app”, then go straight to the Container definitions section and click “Add container”. Name the Container as “sample-rails-app”, and set image location in the format “repository-url/image:tag”. In the new browser tab, go to the ECR to copy the image URI. In my case, it was: “212516879399.dkr.ecr.eu-central-1.amazonaws.com/sample-rails-app:latest”.

Set your Memory Limit to the recommended 300-500MiB. Now, the most tricky thing – Port Mapping.

Our app runs inside a container on port 3000. So put 3000 as the container port. We will enter 0 as a host port, which basically means that it selects a random port. Fortunately, our Application Load Balancer will know this port mapping and will be able to direct traffic correctly. We can even run multiple tasks on this single instance. 

Add the environment variable RAILS_ENV and set it to production.

Now click Add to add our container definition and click Create to finish Task Definition setup.

Service

We have our cluster, load balancer and task definition. Now we have to somehow run these tasks inside our cluster. This is the job of services. Go to the newly created cluster, select the Services tab and click on the Create button. 

Set the Launch type to EC2, add name “sample-rails-app-service”. Set the number of tasks to 1 and click Next Step. On this page, select the Application Load Balancer radio button and choose the existing IAM role for it. In the “Container to load balance” section, you should have already entered a correct container “sample-rails-app:0:3000”, then click “Add to load balancer.”

For “Production listener port”, choose 80:HTTP; as the Target group name, use the one we created before – “sample-rails-app-alb-tg” and click Next Step. Leave Auto Scaling options as they are, click Next Step and Create Service.

Update the ECS Security Group

You can go to created cluster page and check the Tasks tabs, there should be one task running. The Service has started it. Now go to EC2 service page, click Load Balancers and see our Application Load Balancer’s details. You should have there its DNS name. Copy it and open in the browser. It should direct you to our app. Unfortunately, we get the “504 gateway time-out” error. 

The problem is in the security group of our cluster. Its inbound rules do not allow traffic incoming from the load balancer. To fix it, go back to the EC2 panel and click on the Security Groups link. There is a new group that was created during the cluster creation process. It should have the name starting with “EC2ContainerService-sample-rails-app-cluster”. Click on it and edit the inbound rules. As we want to allow any traffic from our VPC, go to the Amazon VPC panel and check what’s your VPC IPv4 CIDR. Set the rule type to “All traffic” and the source to IPv4 CIDR. Save this rule and try to load the balancer’s DNS name. 

Hopefully, you see just as I do 🙂

Read More

GraphQL Ruby. What about performance?

Rails and Other Means of Transport

Rails Development with TMUX, Vim, Fzf + Ripgrep

Related articles

Software Development

Build Future-Proof Web Apps: Insights from The Codest’s Expert Team

Discover how The Codest excels in creating scalable, interactive web applications with cutting-edge technologies, delivering seamless user experiences across all platforms. Learn how our expertise drives digital transformation and business...

THECODEST
Software Development

Top 10 Latvia-Based Software Development Companies

Learn about Latvia's top software development companies and their innovative solutions in our latest article. Discover how these tech leaders can help elevate your business.

thecodest
Enterprise & Scaleups Solutions

Java Software Development Essentials: A Guide to Outsourcing Successfully

Explore this essential guide on successfully outsourcing Java software development to enhance efficiency, access expertise, and drive project success with The Codest.

thecodest
Software Development

The Ultimate Guide to Outsourcing in Poland

The surge in outsourcing in Poland is driven by economic, educational, and technological advancements, fostering IT growth and a business-friendly climate.

TheCodest
Enterprise & Scaleups Solutions

The Complete Guide to IT Audit Tools and Techniques

IT audits ensure secure, efficient, and compliant systems. Learn more about their importance by reading the full article.

The Codest
Jakub Jakubowicz CTO & Co-Founder

Subscribe to our knowledge base and stay up to date on the expertise from the IT sector.

    About us

    The Codest – International software development company with tech hubs in Poland.

    United Kingdom - Headquarters

    • Office 303B, 182-184 High Street North E6 2JA
      London, England

    Poland - Local Tech Hubs

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Warsaw, Poland

      The Codest

    • Home
    • About us
    • Services
    • Case Studies
    • Know How
    • Careers
    • Dictionary

      Services

    • It Advisory
    • Software Development
    • Backend Development
    • Frontend Development
    • Staff Augmentation
    • Backend Developers
    • Cloud Engineers
    • Data Engineers
    • Other
    • QA Engineers

      Resources

    • Facts and Myths about Cooperating with External Software Development Partner
    • From the USA to Europe: Why do American startups decide to relocate to Europe
    • Tech Offshore Development Hubs Comparison: Tech Offshore Europe (Poland), ASEAN (Philippines), Eurasia (Turkey)
    • What are the top CTOs and CIOs Challenges?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Copyright © 2025 by The Codest. All rights reserved.

    en_USEnglish
    de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek en_USEnglish