This document outlines the complete deployment process for AushadhiAI, using GitHub Pages for the frontend and AWS Elastic Beanstalk for the containerized backend.
- Architecture Overview
- Prerequisites
- 1. Repository Preparation
- 2. AWS Infrastructure Setup
- 3. GitHub Repository Configuration
- 4. Deployment Process
- 5. Post-Deployment Configuration
- 6. Testing and Verification
- 7. Troubleshooting
- 8. Enhancements and Next Steps
- File References
┌─────────────────┐ HTTPS ┌──────────────────┐
│ │ ───────────► │ │
│ GitHub Pages │ │ AWS Elastic │
│ (Frontend) │ ◄─────────── │ Beanstalk │
│ │ REST │ (Backend API) │
└─────────────────┘ └──────────────────┘
▲ ▲
│ │
│ CI/CD │ CI/CD
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ │ │ │
│ GitHub Actions │ │ Amazon ECR │
│ (Frontend) │ │ (Container │
│ │ │ Registry) │
└─────────────────┘ └──────────────────┘
Key Components:
- Frontend: Static HTML/CSS/JS hosted on GitHub Pages
- Backend: Python FastAPI application running in Docker on AWS Elastic Beanstalk
- CI/CD: GitHub Actions for automated deployment
- Container Registry: Amazon ECR for storing Docker images
Before starting, ensure you have:
-
AWS Account with access to:
- Elastic Beanstalk
- ECR (Elastic Container Registry)
- IAM (Identity and Access Management)
- S3 (Simple Storage Service)
- CloudWatch
-
GitHub Account with:
- Repository for the AushadhiAI application
- Permissions to configure GitHub Actions and repository settings
-
Local Development Environment with:
- Git
- AWS CLI
- Docker (for local testing)
- Text editor
-
API Keys and Credentials:
- Azure Vision API key and endpoint (used by the application)
Your repository should have this structure:
/
├── backend/ # Backend Python application
├── assets/ # Frontend assets (images, etc.)
├── .github/workflows/ # GitHub Actions workflow files
├── index.html # Main frontend page
├── script.js # Frontend JavaScript
├── styles.css # Frontend styles
├── Dockerfile # Docker configuration for backend
├── requirements.txt # Python dependencies
├── .dockerignore # Files to exclude from Docker
└── .env.example # Example environment variables
Ensure your Dockerfile is properly configured:
FROM python:3.9-slim
WORKDIR /app
# Copy requirements file and install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy the backend code
COPY backend/ /app/
# Environment variables that can be overridden during deployment
ENV PORT=8007
ENV HOST="0.0.0.0"
ENV AZURE_VISION_ENDPOINT=""
ENV AZURE_VISION_KEY=""
# Add AWS-specific health check endpoint configuration
ENV PYTHONUNBUFFERED=1
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8007/api/health || exit 1
# Expose the port
EXPOSE 8007
# Launch the app using uvicorn server
CMD uvicorn app:app --host ${HOST} --port ${PORT}Create a .dockerignore file:
.git
.github
.gitignore
.idea
.vscode
__pycache__/
*.py[cod]
*$py.class
*.so
.env
env/
venv/
ENV/
node_modules/
frontend/
*.log
Ensure your requirements.txt contains all necessary dependencies:
fastapi==0.104.1
uvicorn==0.23.2
python-multipart==0.0.6
pillow==10.0.0
requests==2.31.0
python-dotenv==1.0.0
opencv-python==4.8.0.76
numpy==1.25.2
httpx==0.24.1
pydantic==2.4.2
azure-cognitiveservices-vision-computervision==0.9.0
azure-core==1.29.3
fuzzywuzzy==0.18.0
python-Levenshtein==0.21.1
Create GitHub Actions workflow files:
name: Deploy Frontend to GitHub Pages
on:
push:
branches: [ main ]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Update API URL for production
run: |
# Replace the API_URL with the AWS Elastic Beanstalk production URL
# The format is typically http://[environment-name].[region].elasticbeanstalk.com
sed -i 's|const API_URL = .*|const API_URL = "http://aushadhi-production.us-east-1.elasticbeanstalk.com";|g' script.js
sed -i 's|const API_URL = .*|const API_URL = "http://aushadhi-production.us-east-1.elasticbeanstalk.com";|g' index.html
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
path: '.'
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2name: Deploy Backend to AWS
on:
push:
branches: [ main ]
paths:
- 'backend/**'
- 'Dockerfile'
- 'requirements.txt'
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: aushadhi-backend
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
- name: Generate Dockerrun.aws.json
run: |
cat > Dockerrun.aws.json << EOF
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "${{ steps.login-ecr.outputs.registry }}/aushadhi-backend:${{ github.sha }}",
"Update": "true"
},
"Ports": [
{
"ContainerPort": 8007,
"HostPort": 8007
}
],
"Volumes": [],
"Logging": "/var/log"
}
EOF
- name: Deploy to Elastic Beanstalk
uses: einaregilsson/beanstalk-deploy@v20
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: aushadhi-backend
environment_name: aushadhi-production
version_label: aushadhi-${{ github.sha }}
region: ${{ secrets.AWS_REGION }}
deployment_package: Dockerrun.aws.json
existing_bucket_name: ${{ secrets.AWS_S3_BUCKET }}This user will have permissions to deploy to ECR and Elastic Beanstalk.
# Create IAM user for GitHub Actions
aws iam create-user --user-name github-actions-aushadhi
# Create policy document for GitHub Actions permissions
cat > github-actions-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"elasticbeanstalk:*",
"s3:*",
"ec2:*",
"elasticloadbalancing:*",
"autoscaling:*",
"cloudwatch:*",
"logs:*",
"ecr:*"
],
"Resource": "*"
}
]
}
EOF
# Create the policy
aws iam create-policy --policy-name AushadhiGitHubActionsPolicy --policy-document file://github-actions-policy.json
# Get your AWS account ID
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
# Attach the policy to the user
aws iam attach-user-policy --user-name github-actions-aushadhi --policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/AushadhiGitHubActionsPolicy
# Create access key for the user
aws iam create-access-key --user-name github-actions-aushadhi
# IMPORTANT: Save the output of this command - you will need AccessKeyId and SecretAccessKey for GitHub Secrets# Set your AWS region
AWS_REGION="us-east-1" # Change to your preferred region
# Create S3 bucket with unique name
S3_BUCKET_NAME="aushadhi-eb-deployments-$AWS_ACCOUNT_ID"
aws s3 mb s3://$S3_BUCKET_NAME --region $AWS_REGION# Create ECR repository for the container images
aws ecr create-repository --repository-name aushadhi-backend --image-scanning-configuration scanOnPush=true# Create Elastic Beanstalk application
aws elasticbeanstalk create-application --application-name aushadhi-backend --description "AushadhiAI Backend API"
# Create options configuration file
cat > eb-options.json << 'EOF'
[
{
"Namespace": "aws:autoscaling:launchconfiguration",
"OptionName": "IamInstanceProfile",
"Value": "aws-elasticbeanstalk-ec2-role"
},
{
"Namespace": "aws:elasticbeanstalk:application:environment",
"OptionName": "AZURE_VISION_ENDPOINT",
"Value": "https://your-vision-service.cognitiveservices.azure.com/"
},
{
"Namespace": "aws:elasticbeanstalk:application:environment",
"OptionName": "AZURE_VISION_KEY",
"Value": "your-vision-api-key"
},
{
"Namespace": "aws:elasticbeanstalk:application:environment",
"OptionName": "ALLOWED_ORIGINS",
"Value": "https://harryhome1.github.io,http://localhost:8006"
},
{
"Namespace": "aws:elasticbeanstalk:environment",
"OptionName": "EnvironmentType",
"Value": "SingleInstance"
},
{
"Namespace": "aws:elasticbeanstalk:environment",
"OptionName": "ServiceRole",
"Value": "aws-elasticbeanstalk-service-role"
}
]
EOF
# Replace the placeholder values with your actual values
sed -i 's|https://your-vision-service.cognitiveservices.azure.com/|YOUR_ACTUAL_VISION_ENDPOINT|g' eb-options.json
sed -i 's|your-vision-api-key|YOUR_ACTUAL_VISION_API_KEY|g' eb-options.json
sed -i 's|https://harryhome1.github.io|YOUR_GITHUB_PAGES_URL|g' eb-options.json
# Create Elastic Beanstalk environment
aws elasticbeanstalk create-environment \
--application-name aushadhi-backend \
--environment-name aushadhi-production \
--solution-stack-name "64bit Amazon Linux 2 v3.5.1 running Docker" \
--option-settings file://eb-options.jsonIn your GitHub repository, go to Settings → Secrets and variables → Actions, and add these secrets:
| Secret Name | Description | Example Value |
|---|---|---|
AWS_ACCESS_KEY_ID |
IAM user access key | AKIA1234567890ABCDEF |
AWS_SECRET_ACCESS_KEY |
IAM user secret key | wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY |
AWS_REGION |
AWS region | us-east-1 |
AWS_S3_BUCKET |
S3 bucket for deployments | aushadhi-eb-deployments-123456789012 |
- Go to your repository on GitHub
- Navigate to Settings → Pages
- Under "Source", select "GitHub Actions"
Make sure your frontend code is configured to use environment-specific API endpoints:
In script.js and any other frontend files, ensure the API URL is configurable:
// API Configuration - will be updated during deployment
const API_URL = 'http://localhost:8007';
// For production deployment, set API_BASE_URL to your AWS endpoint
// const API_URL = 'http://aushadhi-production.us-east-1.elasticbeanstalk.com';-
Commit and Push All Changes:
git add . git commit -m "Configure for AWS deployment" git push origin main
-
Trigger Backend Deployment:
- Go to Actions tab in your GitHub repository
- Select "Deploy Backend to AWS" workflow
- Click "Run workflow" and select the main branch
-
Monitor Backend Deployment:
- Check the workflow logs in GitHub Actions
- Verify deployment status in AWS Elastic Beanstalk console
- Note the Elastic Beanstalk URL (e.g.,
http://aushadhi-production.us-east-1.elasticbeanstalk.com)
-
Update Frontend Configuration:
- Update the deployed backend URL in the GitHub workflow file:
# In .github/workflows/deploy-frontend.yml sed -i 's|http://aushadhi-production.us-east-1.elasticbeanstalk.com|YOUR_ACTUAL_EB_URL|g' .github/workflows/deploy-frontend.yml git add .github/workflows/deploy-frontend.yml git commit -m "Update backend URL in frontend deployment" git push origin main
-
Trigger Frontend Deployment:
- Go to Actions tab in your GitHub repository
- Select "Deploy Frontend to GitHub Pages" workflow
- Click "Run workflow" and select the main branch
-
Monitor Frontend Deployment:
- Check the workflow logs in GitHub Actions
- Once complete, your site will be available at:
https://harryhome1.github.io/INTRO-AushadhiAI/
After initial setup, deployments will be triggered automatically:
- Backend: When changes are made to files in the
backend/directory,Dockerfile, orrequirements.txt - Frontend: When any changes are pushed to the main branch
For manual deployments, you can use the "Run workflow" button in the GitHub Actions tab.
Create a CloudWatch dashboard to monitor your application:
# Create CloudWatch dashboard configuration
cat > cloudwatch-dashboard.json << 'EOF'
{
"widgets": [
{
"type": "metric",
"x": 0,
"y": 0,
"width": 12,
"height": 6,
"properties": {
"metrics": [
[ "AWS/ElasticBeanstalk", "EnvironmentHealth", "EnvironmentName", "aushadhi-production" ]
],
"period": 300,
"stat": "Average",
"region": "us-east-1",
"title": "Environment Health"
}
},
{
"type": "metric",
"x": 12,
"y": 0,
"width": 12,
"height": 6,
"properties": {
"metrics": [
[ "AWS/EC2", "CPUUtilization", "InstanceId", "i-012345abcdef" ]
],
"period": 300,
"stat": "Average",
"region": "us-east-1",
"title": "CPU Utilization"
}
},
{
"type": "metric",
"x": 0,
"y": 6,
"width": 12,
"height": 6,
"properties": {
"metrics": [
[ "AWS/EC2", "NetworkIn", "InstanceId", "i-012345abcdef" ],
[ "AWS/EC2", "NetworkOut", "InstanceId", "i-012345abcdef" ]
],
"period": 300,
"stat": "Average",
"region": "us-east-1",
"title": "Network Traffic"
}
}
]
}
EOF
# Get your EC2 instance ID from Elastic Beanstalk
EC2_INSTANCE_ID=$(aws elasticbeanstalk describe-environment-resources --environment-name aushadhi-production --query "EnvironmentResources.Instances[0].Id" --output text)
# Update instance ID in dashboard configuration
sed -i "s/i-012345abcdef/$EC2_INSTANCE_ID/g" cloudwatch-dashboard.json
# Create CloudWatch dashboard
aws cloudwatch put-dashboard --dashboard-name AushadhiAI --dashboard-body file://cloudwatch-dashboard.jsonCreate alarms for critical metrics:
# Create an alarm for high CPU utilization
aws cloudwatch put-metric-alarm \
--alarm-name "AushadhiAI-HighCPU" \
--alarm-description "Alarm when CPU exceeds 80% for 5 minutes" \
--metric-name CPUUtilization \
--namespace AWS/EC2 \
--statistic Average \
--period 300 \
--threshold 80 \
--comparison-operator GreaterThanThreshold \
--dimensions "Name=InstanceId,Value=$EC2_INSTANCE_ID" \
--evaluation-periods 1 \
--alarm-actions arn:aws:sns:us-east-1:$AWS_ACCOUNT_ID:AushadhiAlerts
# Create an alarm for health status changes
aws cloudwatch put-metric-alarm \
--alarm-name "AushadhiAI-HealthStatus" \
--alarm-description "Alarm when environment becomes degraded or severe" \
--metric-name EnvironmentHealth \
--namespace AWS/ElasticBeanstalk \
--statistic Maximum \
--period 300 \
--threshold 20 \
--comparison-operator GreaterThanThreshold \
--dimensions "Name=EnvironmentName,Value=aushadhi-production" \
--evaluation-periods 1 \
--alarm-actions arn:aws:sns:us-east-1:$AWS_ACCOUNT_ID:AushadhiAlertsIf you have a custom domain, you can set it up with Route 53:
# Create hosted zone for your domain (if not already created)
aws route53 create-hosted-zone --name yourdomain.com --caller-reference $(date +%s)
# Save the hosted zone ID
HOSTED_ZONE_ID=$(aws route53 list-hosted-zones-by-name --dns-name yourdomain.com --query "HostedZones[0].Id" --output text | sed 's|/hostedzone/||')
# Create record configuration
cat > route53-records.json << EOF
{
"Changes": [
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "api.yourdomain.com",
"Type": "CNAME",
"TTL": 300,
"ResourceRecords": [
{
"Value": "aushadhi-production.us-east-1.elasticbeanstalk.com"
}
]
}
}
]
}
EOF
# Create the DNS record
aws route53 change-resource-record-sets --hosted-zone-id $HOSTED_ZONE_ID --change-batch file://route53-records.json# Check if the backend API is accessible
curl http://aushadhi-production.us-east-1.elasticbeanstalk.com/api/health
# Expected response:
# {"status":"healthy","services":{"ocr":"active","medication_db":"active","api":"active"}}- Open your browser and navigate to
https://harryhome1.github.io/INTRO-AushadhiAI/ - Check browser console for any errors related to API connections
- Try uploading a prescription image to test the complete flow
-
Prescription Upload Test:
- Upload a valid prescription image
- Verify that the prescription is analyzed and medications are detected
- Check that medication details are properly displayed
-
Error Handling Test:
- Upload an invalid file
- Verify that appropriate error messages are displayed
-
Responsive Design Test:
- Test the application on various screen sizes
- Ensure the interface is responsive and usable on mobile devices
| Issue | Possible Cause | Solution |
|---|---|---|
| Elastic Beanstalk deployment fails | Insufficient permissions | Verify IAM user has all required permissions |
| Container fails to start | Environment variables missing | Check Elastic Beanstalk environment configuration |
| CORS errors in browser | Incorrect ALLOWED_ORIGINS | Update ALLOWED_ORIGINS in Elastic Beanstalk configuration |
| GitHub Pages deployment fails | Issues with GitHub Actions | Check workflow logs for specific errors |
| API returning 500 errors | Application error | Check CloudWatch logs for detailed error messages |
# Get recent logs from Elastic Beanstalk
aws elasticbeanstalk request-environment-info --environment-name aushadhi-production --info-type tail
# After a few seconds, retrieve the logs
aws elasticbeanstalk retrieve-environment-info --environment-name aushadhi-production --info-type tail# SSH into the EC2 instance (if needed)
# First, get the key pair name
KEY_PAIR=$(aws ec2 describe-instances --instance-ids $EC2_INSTANCE_ID --query "Reservations[0].Instances[0].KeyName" --output text)
# Download the key pair (if you have access to it)
# Connect to the instance
ssh -i your-key.pem ec2-user@$EC2_INSTANCE_ID
# Check Docker container status
docker ps -a
# View container logs
docker logs $(docker ps -q --filter "name=aushadhi")-
HTTPS Configuration:
- Set up AWS Certificate Manager for your domain
- Configure HTTPS for Elastic Beanstalk
- Update frontend API URLs to use HTTPS
-
AWS WAF Integration:
- Set up AWS WAF to protect against common web exploits
- Configure rate limiting to prevent abuse
-
Secret Management:
- Use AWS Secrets Manager for sensitive credentials
- Rotate credentials periodically
-
Content Delivery Network:
- Set up AWS CloudFront to accelerate content delivery
- Configure caching policies for static assets
-
Auto Scaling:
- Configure Auto Scaling for your Elastic Beanstalk environment
- Set up scaling policies based on traffic patterns
-
Database Integration:
- Add Amazon RDS for persistent data storage
- Implement caching with Amazon ElastiCache
-
Enhanced Monitoring:
- Set up AWS X-Ray for distributed tracing
- Implement custom CloudWatch metrics for application-specific monitoring
-
Alerting Improvements:
- Configure Amazon SNS topics for different alert levels
- Set up email or SMS notifications for critical alerts
-
Log Analysis:
- Use CloudWatch Logs Insights for advanced log analysis
- Implement centralized logging with Amazon OpenSearch Service
Here's a summary of all configuration files used in this deployment:
| File | Purpose | Location |
|---|---|---|
Dockerfile |
Container configuration | Repository root |
.dockerignore |
Files to exclude from container | Repository root |
requirements.txt |
Python dependencies | Repository root |
eb-options.json |
Elastic Beanstalk configuration | During AWS setup |
github-actions-policy.json |
IAM policy for GitHub Actions | During AWS setup |
cloudwatch-dashboard.json |
CloudWatch dashboard | Post-deployment |
route53-records.json |
DNS records configuration | Optional, for custom domain |
.github/workflows/deploy-frontend.yml |
GitHub Actions for frontend | Repository |
.github/workflows/deploy-backend-aws.yml |
GitHub Actions for backend | Repository |
This deployment plan was prepared for the AushadhiAI project hosted at https://github.com/harryhome1/INTRO-AushadhiAI.