Introduction

While working with a legacy Rails application is always painful considering outdated dependencies, recurring bugs, and most importantly to easily deploy it, it is a tough journey.

I decided to give AWS ECS a try and Docker-ize my application to get rid of the pain dealing with dependencies, Ruby versions as well as deploying it on the cloud.

After reading throughout AWS documentation I realized that now you can actually deploy your application using just docker-compose.yml file and it helps you to set up your stack with CloudFormation that gives you the readability of working with Docker compose.

Before moving forward you need to have your AWS credentials stored in ~/.aws/credentials and you need to create a context in Docker using docker context create ecs myecscontext. Checkout Docker ECS integration here.

Deployment

Here are the steps I followed to deploy my legacy Rails 2.x application to AWS ECS:

  1. I built a Docker image and pushed it to AWS ECR
  2. I created AWS RDS and added the credentials in docker-compose.yml
  3. I designed docker-compose.yml with 2 services Web and Redis in the same network bridge.

All the services declared in docker-compose.yml need to be in the same network using driver: bridge

# Dockerfile
FROM ruby:1.9.3

RUN apt-get update && apt-get install -y \
  apt-transport-https ca-certificates \
  curl \
  build-essential \
  libsasl2-dev &&\
  curl -sL https://deb.nodesource.com/setup_10.x | bash - && \
  curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
  echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
  apt-get update && apt-get install -y --force-yes nodejs yarn

RUN mkdir /app
WORKDIR /app
COPY . .
ADD ./config/unicorn.rb /app/config/unicorn.rb

# Install Gems.
RUN bundle install

version: '3.0'
services:
  rails-web:
    image: rails-app
    command: bundle exec unicorn -p 80 -c /app/config/unicorn.rb
    ports:
      - 80:80
    environment:
      RAILS_ENV: production
      RDS_DATABASE: xxxxx
      RDS_USERNAME: xxxxx
      RDS_PASSWORD: xxxxx
      RDS_HOST: xxxxxxxxx
      REDIS_URI: xxxxxxxxxx
      REDIS_URL: xxxxxxxxxx
    networks:
      - rails-network
    depends_on:
      - rails-redis

  rails-redis:
    image: redis:alpine
    networks:
      - rails-network

networks:
  rails-network:
    driver: bridge

Before deploying your application keep in mind is to make sure you have your Rails app database/config.yml and redis.yml and service dependencies are explicitly declared in the configuration (e.g. SENTRY_DSN).

Then simply run docker compose up docker-compose-up-terminal

And simply you need to wait until all the resources are created in CloudFormation and run docker compose ps which you can see your DSN is binded to Web service and then you can open it in your browser to make sure everything is working fine and later mapping it to your custom domain on AWS Route53.

Conclusion

So far the only problem I had is CloudFormation stacks stuck in UPDATE_ROLLBACK_FAILED when I accidentally run docker compose up or docker compse down and immmidatly cancelled.

I recommend to give it try and hopefully you can get some hints from this post that can help you along the way. Cheers!