CI/CD for Deploying Docker Application on EC2 with GitHub Actions

This guide explains how to set up a CI/CD pipeline to automatically deploy a Dockerized FastAPI app (or any containerized app) to an EC2 instance using GitHub Actions.


:brick: Prerequisites

  • A running EC2 Ubuntu instance
  • Your app is containerized with Docker Compose
  • SSH access to EC2 (user: ubuntu or similar)
  • Your app code is hosted on GitHub
  • Optional: DNS domain and SSL setup via Nginx + Let’s Encrypt

:locked_with_key: Step 1: Generate an SSH Deploy Key

Create a new SSH key pair (locally or in CI):

ssh-keygen -t ed25519 -C "github-deploy-key"

:locked_with_key: Step 2: Add Public Key to EC2

  1. SSH into EC2:
  ssh ubuntu@<your-ec2-ip>
  1. Open the authorized_keys file:
nano ~/.ssh/authorized_keys
  1. Paste in the contents of id_ed25519.pub.
  2. Set proper permissions:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

:white_check_mark: You can have multiple lines in authorized_keys.

:locked: Step 3: Allow Docker Without sudo

On EC2:

sudo usermod -aG docker ubuntu

Then log out and log back in (or reboot):

exit

Reconnect and test:

docker ps

:key: Step 4: Add GitHub Secrets

Go to your GitHub repo β†’ Settings β†’ Secrets and variables β†’ Actions, and add:

Name Description
EC2_HOST EC2 IP or DNS
EC2_USER SSH username (e.g., ubuntu)
EC2_SSH_KEY Content of your private key id_ed25519

:gear: Step 5: Create GitHub Actions Workflow

Create a file at .github/workflows/deploy.yml:

name: Deploy to EC2

on:
  push:
    branches: [main]  # Update if using another branch

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: SSH & Deploy
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USER }}
          key: ${{ secrets.EC2_SSH_KEY }}
          script: |
            cd /home/ubuntu/translation-worker-api
            git pull origin main
            docker-compose down
            docker-compose up -d --build

:rocket: Step 6: Push to GitHub to Deploy

git add .
git commit -m "Deploying via GitHub Actions"
git push origin main

Check GitHub β†’ Actions tab to see the workflow progress.

:white_check_mark: Example Directory Structure

translation-worker-api/
β”œβ”€β”€ .github/
β”‚ └── workflows/
β”‚ └── deploy.yml
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ app/
β”‚ └── main.py
└── …

:rocket: Optional Enhancements

  • Add .env file support for Docker Compose
  • Configure Nginx + Certbot for subdomains and SSL
  • Use GitHub environments (staging, production)
  • Add deploy notifications (e.g., Slack, Discord)
  • Write a deploy.sh script with error handling
1 Like