Sitemap

Automating Deployment of a Flask Application to AWS ECS with GitHub Actions

15 min readMay 16, 2025

--

You no longer need to spend hours at your terminal deploying your app to AWS. Now, with a single git push, you can convert your code into a Docker container and publish it on AWS. In this article, we’ll use GitHub Actions to automatically:

  • Convert the Flask-based application into a Docker image
  • Push it to ECR
  • Launch it on ECS

We’ll build a serverless CI/CD pipeline, step by step!

Requirements

To successfully follow the steps in this article, make sure you have the following accounts, tools, and prerequisite knowledge:

Accounts & Cloud Environment

  • GitHub account — for repository and GitHub Actions usage
  • AWS account — with sufficient permissions to access ECR, ECS, and IAM

🛠️ Required Tools (must be installed and configured locally)

  • Git — for version control
  • Docker Engine — to build and test Docker images
  • AWS CLI — to interact with AWS services via terminal (AWS credentials)

Technologies Used

  • GitHub Actions → Automates CI/CD workflows
  • Docker → Containerizes the Flask application
  • Amazon ECR → Stores Docker images
  • Amazon ECS (Fargate) → Runs containers without managing servers
  • IAM → Manages secure access

Project Structure

flask-ecs-cicd/
├── app/
│ └── app.py
├── Dockerfile
├── requirements.txt
├── README.md
└── .github/
└── workflows/
└── deploy.yml

Creating the Main Folder and File Structure

mkdir flask-ecs-cicd   
cd flask-ecs-cicd
mkdir app
mkdir -p .github/workflows
touch app/app.py Dockerfile requirements.txt README.md .github/workflows/deploy.yml

Flask Application

app/app.py

from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello from Flask on ECS v1"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

Dockerfile

FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY app/ .
CMD ["python", "app.py"]

requirements.txt

Flask==2.3.2

README.md

# Flask App for AWS ECS Deployment
This is a simple Flask application deployed using GitHub Actions to AWS ECS.

Testing the Application Locally

# Build the Docker image:
docker build -t flask-ecs-app .
# Run the container:
docker run -d -p 5000:5000 flask-ecs-app

Open your browser at http://localhost:5000

Preparing the GitHub Repository

  1. Create a new repository named flask-ecs-cicd on GitHub
  2. Push your code:
cd flask-ecs-cicd
git init
git remote add origin https://github.com/username/flask-ecs-cicd.git
git add .
git commit -m "initial commit"
git push -u origin main

☁️ Setting Up AWS Infrastructure

💡 If you prefer to automate the entire deployment process, you can skip most of the manual steps by using the provided Bash scripts (`ecs-setup.sh` and `ecs-cleanup.sh`).
These scripts will handle ECR creation, ECS cluster and service setup, task definition registration, image deployment, and even cleanup.

🛠 OPTIONS 1- Create ECS cluster and ECR repository manually

Amazon ECR (Elastic Container Registry) Creation

AWS Console > ECR > Repositories > Create repository

Repository name: flask-ecs-cicd
Image tag mutability: Mutable
Encryption: AES-256 (default and appropriate)
Image scanning settings: (deprecated — we can skip this)

Click Create repository to create the new repository.

IAM Configuration

The repository is ready. We need two different IAM configurations: one for ECR access via GitHub Actions, and one for running containers on ECS.

Create an IAM User for GitHub

User name: github-actions-user
Access type: Programmatic access

Policy:

  • AmazonEC2ContainerRegistryFullAccess
  • AmazonECS_FullAccess

This user will:

  • Build the Docker image via GitHub Actions
  • Push it to the ECR repository

⚠️ Note: ECS tasks require an execution role with the AmazonECSTaskExecutionRolePolicy.
If you're using
Terraform or AWS CLI, you must create this role manually.
It may be created automatically by the
ECS console wizard, but that is not guaranteed in automation scenarios.

Creating the User

In the console, choose IAM > Users > Add user
User name: github-actions-user
Access type: Programmatic access (API only)

Permissions: Attach policies directly:

  • AmazonEC2ContainerRegistryFullAccess
  • AmazonECS_FullAccess

Create the user and note the Access Key ID and Secret Access Key.

Next, double-click the github-actions-user and select Security credentials.

Click Create access key to generate the CLI credentials.

Download the CSV and save it — these are your GitHub Actions secrets.

ECS Setup

1. Create a Cluster

AWS Console > ECS > Clusters > Create Cluster

Cluster configuration:

  • Cluster name: flask-ecs-cluster
  • Infrastructure: AWS Fargate (serverless)

Leave everything else as default and click Create Cluster.

Cluster created.

2. Define a Task (Container + ECR Image)

AWS Console > ECS > Task Definitions > Create new Task Definition

Task Definition Settings:

Task Definition Name: flask-ecs-task
Launch type: AWS Fargate
Task Size:
CPU: 0.5 vCPU
Memory: 2 GB

🔍 Note on Roles:
ecsTaskExecutionRole must only be used in the Task Execution Role field.
Leave the
Task Role field empty unless your container needs access to AWS services like S3, DynamoDB, etc.

Task Execution Role: ecsTaskExecutionRole
Choose ecsTaskExecutionRole if listed
Otherwise click Create new role to let AWS create it

Configure the container:

  • Name: flask-container
  • Image URI: 339712822099.dkr.ecr.us-east-1.amazonaws.com/flask-ecs-cicd:latest
  • Port: 5000
  • Protocol: TCP (HTTP)

Leave all other options with their default settings and create a Task Definition by clicking the create button.

3. Create a Service (Run the Container on Fargate)

AWS Console > ECS > Clusters > flask-ecs-cluster >Services > Create

Service Details

  • Task definition family: flask-ecs-task
  • Revision: 1 (or latest)
  • Service name: flask-ecs-task-service-ibb

Environment

  • Existing cluster: flask-ecs-cluster
  • Compute configuration: Capacity Provider Strategy (FARGATE)

Deployment Configuration

  • Service type: Replica
  • Desired tasks: 1
  • Availability Zone rebalancing: Enabled

Networking

  • VPC: Default
  • Subnets: Select at least 2 (e.g., us-east-1a, us-east-1b)
  • Security Group: Create new
  • Inbound Rule: TCP 5000 from 0.0.0.0/0
  • Auto-assign public IP: Enabled

Click Create to launch the service.

The service may take a few minutes to stabilize. It will remain in Pending until an image is pushed to ECR.

After waiting a little while, you may get this error because the image cannot be found in the ECR.

To resolve this, push the image to ECR via GitHub Actions or manually with the AWS CLI.

ECR Image Push (Manual Test)

  1. Configure the AWS CLI credentials:
aws configure

2. Log in to ECR:

aws ecr get-login-password — region us-east-1 | \
docker login — username AWS — password-stdin <your-repo-url>

aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin \
339712822099.dkr.ecr.us-east-1.amazonaws.com

3. Build the Docker image:

💡 Note: Make sure you build your Docker image for the correct platform.
AWS Fargate requires
linux/amd64 images. On Apple Silicon (M1/M2), use the following command:

docker buildx build --platform linux/amd64 -t flask-ecs-cicd .

4. Tag the image:

docker tag flask-ecs-cicd:latest <your-repo-url>/flask-ecs-cicd:latest

docker tag flask-ecs-cicd:latest \
339712822099.dkr.ecr.us-east-1.amazonaws.com/flask-ecs-cicd:latest

5. Push the image:

docker push <your-repo-url>/flask-ecs-cicd:latest

docker push 339712822099.dkr.ecr.us-east-1.amazonaws.com/flask-ecs-cicd:latest

Yes, the image was successfully pushed to the ECR repository.

Select a running task to find the ECS public IP and verify your app is working.

After deployment, select a running task in the ECS console to find the public IP address and verify your Flask application is working as expected.

⚠️ If your service does not start or remains in a stopped state, it might be because ECS could not pull the latest image from the ECR registry.
In such cases, you can force a new deployment with the following command:

aws ecs update-service \
--cluster flask-ecs-cluster \
--service flask-ecs-task-service-ibb \
--force-new-deployment

In our project, we tested http://<public-IP>:5000 in the browser (e.g., http://100.28.211.212:5000).

Automating Deploys with GitHub Actions

Now, to enable automatic deploys, define these secrets and variables in the GitHub repository’s Settings → Secrets and Variables:

Secrets

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

Variables

  • AWS_REGION
  • ECR_REPO
  • ECS_CLUSTER
  • ECS_SERVICE

.github/workflows/deploy.yml:

name: Deploy to AWS ECS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ vars.AWS_REGION }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build and Push Docker image to ECR
run: |
docker buildx build \
--platform linux/amd64 \
-t ${{ vars.ECR_REPO }}:stable \
--push .
- name: Force ECS service to redeploy
run: |
aws ecs update-service \
--cluster ${{ vars.ECS_CLUSTER }} \
--service ${{ vars.ECS_SERVICE }} \
--force-new-deployment

✅ Result

Now, on every git push:

  • The Flask application is packaged into a Docker image
  • It is pushed to ECR
  • It is automatically deployed on ECS

🎉 You now have a fully automated, serverless, and secure CI/CD pipeline!

✅ Conclusion

In this article, we explored how to deploy a Flask application to AWS ECS Fargate using GitHub Actions.
We covered the infrastructure setup, Docker image handling, ECR push, task definition, and CI/CD integration.

By automating these steps with GitHub Actions and optional Bash scripts, you can ensure faster, error-free deployments in real-world scenarios.

⚙️ OPTIONS 2- Create ECS Cluster and ECR repository Full Automation with Bash Scripts

For users who prefer terminal-based workflows or need repeatable infrastructure automation, we provide two fully working Bash scripts:

Automated Deployment Script

📄 ecs-setup.sh

#!/bin/bash
# === Disable AWS CLI pager ===
export AWS_PAGER=""
# === Color definitions ===
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

# === Configurable Variables ===
AWS_REGION="us-east-1"
CLUSTER_NAME="flask-cluster"
SERVICE_NAME="flask-service"
TASK_NAME="flask-task"
REPO_NAME="flask-ecr-repo"
CONTAINER_NAME="flask-app"
CONTAINER_PORT=5000
SG_NAME="flask-sg"

# === Step 1: Get AWS Account Info ===
echo -e "${CYAN}${BOLD}Step 1: Getting AWS account info...${NC}"
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
if [ $? -ne 0 ]; then
echo -e "${RED}❌ AWS CLI not configured. Run 'aws configure' first.${NC}"
exit 1
fi
echo -e "${GREEN}✔ AWS Account ID: $ACCOUNT_ID${NC}"

# === Step 2: Get default VPC and Subnet ===
echo -e "\n${CYAN}${BOLD}Step 2: Fetching default VPC and subnet...${NC}"
VPC_ID=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true --query "Vpcs[0].VpcId" --output text)
SUBNET_ID=$(aws ec2 describe-subnets --filters Name=vpc-id,Values=$VPC_ID --query "Subnets[0].SubnetId" --output text)
echo -e "${GREEN}✔ VPC ID: $VPC_ID | Subnet ID: $SUBNET_ID${NC}"

# === Step 3: Check/Create Security Group ===
echo -e "\n${CYAN}${BOLD}Step 3: Creating or using security group '${SG_NAME}'...${NC}"
SG_ID=$(aws ec2 describe-security-groups \
--filters Name=group-name,Values=$SG_NAME Name=vpc-id,Values=$VPC_ID \
--query "SecurityGroups[0].GroupId" \
--output text 2>/dev/null)

if [[ "$SG_ID" == "None" || -z "$SG_ID" ]]; then
SG_ID=$(aws ec2 create-security-group \
--group-name $SG_NAME \
--description "Allow TCP $CONTAINER_PORT" \
--vpc-id $VPC_ID \
--query 'GroupId' --output text)
aws ec2 authorize-security-group-ingress \
--group-id $SG_ID \
--protocol tcp --port $CONTAINER_PORT --cidr 0.0.0.0/0
echo -e "${GREEN}✔ Security group created: $SG_ID${NC}"
else
echo -e "${GREEN}✔ Using existing security group: $SG_ID${NC}"
fi

# === Step 4: Create ECR Repository if needed ===
echo -e "\n${CYAN}${BOLD}Step 4: Creating or checking ECR repository '${REPO_NAME}'...${NC}"
aws ecr describe-repositories --repository-names $REPO_NAME >/dev/null 2>&1
if [ $? -ne 0 ]; then
aws ecr create-repository --repository-name $REPO_NAME
echo -e "${GREEN}✔ ECR repository created.${NC}"
else
echo -e "${GREEN}✔ ECR repository already exists.${NC}"
fi

IMAGE_URL="$ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$REPO_NAME:latest"

# === Step 5: Create IAM Role if needed ===
echo -e "\n${CYAN}${BOLD}Step 5: Creating or checking IAM Role 'ecsTaskExecutionRole'...${NC}"
aws iam get-role --role-name ecsTaskExecutionRole >/dev/null 2>&1
if [ $? -ne 0 ]; then
aws iam create-role --role-name ecsTaskExecutionRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "ecs-tasks.amazonaws.com" },
"Action": "sts:AssumeRole"
}]
}'
aws iam attach-role-policy \
--role-name ecsTaskExecutionRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
echo -e "${YELLOW}⏳ Waiting 10 seconds for IAM propagation...${NC}"
sleep 10
else
echo -e "${GREEN}✔ IAM Role already exists.${NC}"
fi

# === Step 6: Create ECS Cluster if needed ===
echo -e "\n${CYAN}${BOLD}Step 6: Creating or checking ECS Cluster '${CLUSTER_NAME}'...${NC}"
aws ecs describe-clusters --clusters $CLUSTER_NAME --query "clusters[0].status" --output text | grep -q ACTIVE
if [ $? -ne 0 ]; then
aws ecs create-cluster --cluster-name $CLUSTER_NAME
echo -e "${GREEN}✔ ECS Cluster created.${NC}"
else
echo -e "${GREEN}✔ ECS Cluster already exists.${NC}"
fi

# === Step 7: Register Task Definition ===
echo -e "\n${CYAN}${BOLD}Step 7: Registering ECS Task Definition '${TASK_NAME}'...${NC}"
aws ecs register-task-definition \
--family $TASK_NAME \
--requires-compatibilities "FARGATE" \
--network-mode "awsvpc" \
--cpu "256" \
--memory "512" \
--execution-role-arn arn:aws:iam::$ACCOUNT_ID:role/ecsTaskExecutionRole \
--container-definitions "[
{
\"name\": \"$CONTAINER_NAME\",
\"image\": \"$IMAGE_URL\",
\"portMappings\": [
{
\"containerPort\": $CONTAINER_PORT,
\"protocol\": \"tcp\"
}
],
\"essential\": true
}
]"
echo -e "${GREEN}✔ Task definition registered.${NC}"

# === Step 8: Create ECS Service ===
echo -e "\n${CYAN}${BOLD}Step 8: Creating ECS Service '${SERVICE_NAME}'...${NC}"
aws ecs describe-services --cluster $CLUSTER_NAME --services $SERVICE_NAME --query "services[0].status" --output text | grep -q ACTIVE
if [ $? -ne 0 ]; then
aws ecs create-service \
--cluster $CLUSTER_NAME \
--service-name $SERVICE_NAME \
--task-definition $TASK_NAME \
--launch-type FARGATE \
--desired-count 1 \
--network-configuration "awsvpcConfiguration={
subnets=[\"$SUBNET_ID\"],
securityGroups=[\"$SG_ID\"],
assignPublicIp=\"ENABLED\"
}"
echo -e "${GREEN}✔ ECS Service created.${NC}"
else
echo -e "${GREEN}✔ ECS Service already exists.${NC}"
fi

# === Step 9: Docker login to ECR ===
echo -e "\n${CYAN}${BOLD}Step 9: Logging in to Amazon ECR...${NC}"
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin "$ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com"
if [ $? -ne 0 ]; then
echo -e "${RED}❌ Docker login failed. Check IAM ECR permissions.${NC}"
exit 1
fi
echo -e "${GREEN}✔ Docker login successful.${NC}"

# === Step 10: Build & Push Docker image with correct platform ===
echo -e "\n${CYAN}${BOLD}Step 10: Building Docker image for linux/amd64 (Fargate)...${NC}"
docker buildx build --platform linux/amd64 -t $REPO_NAME . --load
docker tag $REPO_NAME:latest $IMAGE_URL
docker push $IMAGE_URL
echo -e "${GREEN}✔ Docker image pushed to ECR.${NC}"

# === Step 11: Force ECS service to redeploy ===
echo -e "\n${CYAN}${BOLD}Step 11: Forcing ECS Service to redeploy new image...${NC}"
aws ecs update-service \
--cluster $CLUSTER_NAME \
--service $SERVICE_NAME \
--force-new-deployment >/dev/null 2>&1

if [ $? -eq 0 ]; then
echo -e "${GREEN}✔ ECS Service successfully redeployed with latest image.${NC}"
else
echo -e "${RED}❌ Failed to force ECS Service redeployment.${NC}"
fi

# === DONE ===
echo -e "\n${CYAN}${BOLD}🎉 Setup complete! Your Flask app is deployed on AWS ECS Fargate.${NC}\n"

This script will:

- Automatically detect default VPC and subnet
- Create or reuse a Security Group
- Create ECR repository (if missing)
- Create ECS Cluster and Task Definition
- Build Docker image for `linux/amd64` (Fargate compatible)
- Push the image to ECR
- Deploy and force update the ECS Service

Run it with:

bash ecs-setup.sh

💡 Useful for CI/CD pipelines or developers who want one-command deployments.

Automated Teardown Script

This script removes all created resources:

  • Stops any running ECS tasks
  • Deletes the ECS service and waits for it to shut down
  • Deletes ECS Cluster
  • Deregisters all task definitions in the family
  • Deletes the ECR repository
  • Removes the Security Group

🧹 ecs-cleanup.sh:

#!/bin/bash
# === Disable AWS CLI pager ===
export AWS_PAGER=""
# === Color codes ===
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

# === Configuration ===
AWS_REGION="us-east-1"
CLUSTER_NAME="flask-cluster"
SERVICE_NAME="flask-service"
TASK_NAME="flask-task"
REPO_NAME="flask-ecr-repo"
SG_NAME="flask-sg"

# === Get AWS account ID ===
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text 2>/dev/null)
if [ $? -ne 0 ]; then
echo -e "${RED}❌ Failed to get AWS account ID. Make sure AWS CLI is configured.${NC}"
exit 1
fi

echo -e "${CYAN}${BOLD}🧹 Starting cleanup of AWS ECS and ECR resources...${NC}"

# === Step 1: Stop running tasks (if any) ===
echo -e "\n${CYAN}${BOLD}Step 1: Checking for running ECS tasks...${NC}"
TASKS=$(aws ecs list-tasks --cluster $CLUSTER_NAME --query "taskArns[]" --output text)
if [ -n "$TASKS" ]; then
echo -e "${YELLOW}Stopping running tasks...${NC}"
for task in $TASKS; do
aws ecs stop-task --cluster $CLUSTER_NAME --task $task >/dev/null 2>&1
echo -e "${GREEN}✔ Stopped task: $task${NC}"
done
else
echo -e "${GREEN}✔ No running tasks found.${NC}"
fi

# === Step 2: Delete ECS Service ===
echo -e "\n${CYAN}${BOLD}Step 2: Deleting ECS service '${SERVICE_NAME}'...${NC}"
aws ecs describe-services --cluster $CLUSTER_NAME --services $SERVICE_NAME --query "services[0].status" --output text | grep -q "ACTIVE"
if [ $? -eq 0 ]; then
aws ecs delete-service --cluster $CLUSTER_NAME --service $SERVICE_NAME --force >/dev/null 2>&1
echo -e "${GREEN}✔ Service deleted.${NC}"
echo -e "${YELLOW}⏳ Waiting for service to become inactive...${NC}"
aws ecs wait services-inactive --cluster $CLUSTER_NAME --services $SERVICE_NAME
else
echo -e "${GREEN}✔ ECS service already deleted or not found.${NC}"
fi

# === Step 3: Delete ECS Cluster ===
echo -e "\n${CYAN}${BOLD}Step 3: Deleting ECS cluster '${CLUSTER_NAME}'...${NC}"
aws ecs delete-cluster --cluster $CLUSTER_NAME >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo -e "${GREEN}✔ Cluster deleted.${NC}"
else
echo -e "${YELLOW}⚠️ Cluster not found or already deleted.${NC}"
fi

# === Step 4: Deregister all Task Definitions ===
echo -e "\n${CYAN}${BOLD}Step 4: Deregistering ECS Task Definitions (family: $TASK_NAME)...${NC}"
TASK_DEFS=$(aws ecs list-task-definitions --family-prefix $TASK_NAME --query "taskDefinitionArns[]" --output text)
if [ -n "$TASK_DEFS" ]; then
for def in $TASK_DEFS; do
aws ecs deregister-task-definition --task-definition $def >/dev/null 2>&1
echo -e "${GREEN}✔ Deregistered: $def${NC}"
done
else
echo -e "${GREEN}✔ No task definitions to deregister.${NC}"
fi

# === Step 5: Delete ECR Repository ===
echo -e "\n${CYAN}${BOLD}Step 5: Deleting ECR repository '${REPO_NAME}'...${NC}"
aws ecr delete-repository --repository-name $REPO_NAME --force >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo -e "${GREEN}✔ ECR repository deleted.${NC}"
else
echo -e "${YELLOW}⚠️ Repository not found or already deleted.${NC}"
fi

# === Step 6: Delete Security Group ===
echo -e "\n${CYAN}${BOLD}Step 6: Deleting Security Group '${SG_NAME}'...${NC}"
VPC_ID=$(aws ec2 describe-vpcs --filters "Name=isDefault,Values=true" --query "Vpcs[0].VpcId" --output text)
SG_ID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=$SG_NAME Name=vpc-id,Values=$VPC_ID --query "SecurityGroups[0].GroupId" --output text 2>/dev/null)

if [ "$SG_ID" != "None" ] && [ -n "$SG_ID" ]; then
aws ec2 delete-security-group --group-id $SG_ID >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo -e "${GREEN}✔ Security group deleted.${NC}"
else
echo -e "${YELLOW}⚠️ Could not delete security group. It might still be attached or in use.${NC}"
fi
else
echo -e "${GREEN}✔ Security group not found or already deleted.${NC}"
fi

# === Done ===
echo -e "\n${CYAN}${BOLD}✅ Cleanup completed successfully.${NC}\n"

Run it with:

bash ecs-cleanup.sh

⚠️ Make sure you don’t need any remaining resources before running the cleanup.

📎 GitHub Repository

You can find all code, scripts, and complete instructions in the following GitHub repository:
👉 https://github.com/hakanbayraktar/flask-ecs-cicd

--

--

No responses yet