๐ Multi-Application CI/CD on AWS (Production-Style)
Source: Dev.to
Project Goal
- Developers push code to GitHub.
- GitHub Actions automatically:
- Tests code
- Builds Docker images
- Pushes images to AWS ECR
- Deploys to AWS ECS (Fargate) or EC2 + Docker
- End users access apps via HTTPS (ALB + ACM)
- Logs & monitoring via CloudWatch
- Supports rolling / blueโgreen deployment
HighโLevel Architecture
flowchart TD
Developer -->|push| GitHubRepo[GitHub Repo (App1, App2, App3)]
GitHubRepo --> GitHubActions[GitHub Actions (CI/CD)]
GitHubActions -->|Test| Test
GitHubActions -->|Docker Build| Build
GitHubActions -->|Push to ECR| ECR[AWS ECR (Images)]
ECR --> ECS[AWS ECS (Fargate)]
ECS --> ALB[Application Load Balancer]
ALB --> EndUsers[End Users (HTTPS)]
Repository Structure
multi-app-devops/
โโโ app1/
โ โโโ Dockerfile
โ โโโ src/
โโโ app2/
โ โโโ Dockerfile
โ โโโ src/
โโโ app3/
โ โโโ Dockerfile
โ โโโ src/
โโโ .github/
โโโ workflows/
โโโ deploy.yml
Each application is independent but deployed via the same pipeline logic.
Step 1: AWS Account & IAM
Attach the following managed policies to the CI/CD IAM user/role:
AmazonEC2FullAccessAmazonECS_FullAccessAmazonEC2ContainerRegistryFullAccessCloudWatchFullAccessIAMReadOnlyAccess
Create an Access Key for programmatic access.
Step 2: Networking (VPC)
- Create a VPC with two public subnets.
- Attach an Internet Gateway and configure a route table.
- Security groups:
- ALB โ inbound ports
80and443 - ECS tasks โ inbound ports
3000,5000,80(as required by each app)
- ALB โ inbound ports
Step 3: Create ECR Repositories
Create one repository per application:
app1-ecrapp2-ecrapp3-ecr
Record the following for later use:
- AWS Account ID
- Region
- Repository URI (e.g.,
123456789012.dkr.ecr.us-east-1.amazonaws.com/app1)
Step 4: Dockerize Applications
Example Dockerfile (use the same pattern for each app):
# Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
Step 5: ECS Cluster (Fargate)
- Create an ECS cluster.
- Define a Task Definition for each app:
- Container image โ ECR URI
- Port mapping โ appโs exposed port
- CPU & memory settings
- Create a Service for each task definition:
- Launch type: FARGATE
- Attach the service to the ALB target group
- Desired count:
2(high availability)
Step 6: Application Load Balancer
Configure pathโbased routing:
| Path | Target Service |
|---|---|
/app1 | app1-service |
/app2 | app2-service |
/app3 | app3-service |
Step 7: GitHub Secrets
Add the following secrets to the repository:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_ACCOUNT_IDECR_REPO_APP1(full URI)ECR_REPO_APP2(full URI)ECR_REPO_APP3(full URI)
Step 8: GitHub Actions CI/CD Pipeline
.github/workflows/deploy.yml
name: CI-CD Pipeline
on:
push:
branches: [ "main" ]
env:
AWS_REGION: us-east-1
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
run: |
aws ecr get-login-password --region $AWS_REGION \
| docker login --username AWS --password-stdin \
${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.$AWS_REGION.amazonaws.com
- name: Build & Push App1
run: |
docker build -t app1 ./app1
docker tag app1:latest ${{ secrets.ECR_REPO_APP1 }}:latest
docker push ${{ secrets.ECR_REPO_APP1 }}:latest
- name: Deploy App1 to ECS
run: |
aws ecs update-service \
--cluster devops-cluster \
--service app1-service \
--force-new-deployment
# Repeat the build, push, and deploy steps for app2 and app3
Step 9: Monitoring & Logs
- CloudWatch Logs โ capture container stdout/stderr.
- Metrics โ CPU, memory, and network utilization per task.
- Health checks โ configured on the ALB target groups.
Step 10: Security & Best Practices
- Use leastโprivilege IAM policies.
- Enable image scanning in ECR.
- Enforce HTTPS with ACM certificates on the ALB.
- Rotate IAM access keys regularly.
Step 11: Testing Flow
- Developer modifies code and pushes to
main. - GitHub Actions workflow triggers.
- Docker image is rebuilt and pushed to ECR.
- ECS service pulls the new image and performs a rolling deployment.
- End users receive the updated application without downtime.