DEV Community

developerz.ai
developerz.ai

Posted on

Practical CI CD for Rails on AWS

Introduction

Building a reliable CI CD pipeline for a Rails application on AWS does not require exotic tools. In this article I walk through a straightforward setup that uses GitHub Actions, Docker, and Elastic Beanstalk. The goal is to ship code quickly while keeping the production environment stable.

Choosing the right build environment

Start with a GitHub Actions workflow that runs on the latest Ubuntu runner. Install Ruby, Node, and the required system libraries. A typical step looks like this:

name: CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'
      - name: Install dependencies
        run: |
          gem install bundler
          bundle install --jobs 4 --retry 3
          npm ci
      - name: Run tests
        run: bundle exec rspec
Enter fullscreen mode Exit fullscreen mode

The workflow installs the exact Ruby version used in production and caches the bundle and node modules to speed up subsequent runs.

Containerizing the application

Docker provides a consistent runtime across development, CI, and production. Create a Dockerfile that mirrors the Elastic Beanstalk platform configuration:

FROM ruby:3.2-slim
RUN apt-get update && apt-get install -y nodejs

WORKDIR /app
COPY Gemfile*./
RUN bundle install --without development test
COPY..

EXPOSE 3000
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
Enter fullscreen mode Exit fullscreen mode

Build the image in the CI workflow and push it to Amazon ECR:

- name: Build Docker image
  run: |
    docker build -t ${{ secrets.ECR_REPO }}:${{ github.sha }}.
    aws ecr get-login-password | docker login --username AWS --password-stdin ${{ secrets.ECR_REGISTRY }}
    docker push ${{ secrets.ECR_REPO }}:${{ github.sha }}
Enter fullscreen mode Exit fullscreen mode

Deploying to Elastic Beanstalk

Elastic Beanstalk can pull the image directly from ECR. Define an environment configuration file that sets the image tag based on the Git SHA. The deployment step in the workflow triggers a new application version:

- name: Deploy to Elastic Beanstalk
  run: |
    aws elasticbeanstalk create-application-version \
      --application-name developerz-app \
      --version-label ${{ github.sha }} \
      --source-bundle S3Bucket=${{ secrets.S3_BUCKET }},S3Key=app.zip
    aws elasticbeanstalk update-environment \
      --environment-name developerz-prod \
      --version-label ${{ github.sha }}
Enter fullscreen mode Exit fullscreen mode

Because the version label is the commit SHA, each deployment is uniquely identifiable.

Monitoring and rollback

Add a health check script that runs after deployment. If the health endpoint returns an error, trigger a rollback to the previous version using the Elastic Beanstalk CLI. This safety net prevents a bad commit from staying live.

- name: Health check
  run: |
    STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://myapp.example.com/health)
    if [ $STATUS -ne 200 ]; then
      aws elasticbeanstalk update-environment --environment-name developerz-prod --version-label ${{ github.event.before }}
    fi
Enter fullscreen mode Exit fullscreen mode

Lessons learned

  • Keep the CI environment as close as possible to production. Docker images eliminate “works on my machine” surprises.
  • Use the commit SHA as the version identifier. It makes tracing a problem back to a change trivial.
  • Automate health checks and rollbacks. A small script can save hours of manual debugging.

Conclusion

A minimal CI CD pipeline built with GitHub Actions, Docker, and Elastic Beanstalk provides fast feedback and reliable deployments for Rails apps on AWS. The setup is inexpensive, scales with traffic, and requires only a few YAML files to maintain. Feel free to adapt the snippets to your own workflow.


Author: senior engineer at developerz.ai

Top comments (0)