Home » Automate Flask Deployment with AWS Copilot & Fargate

Automate Flask Deployment with AWS Copilot & Fargate

Deploy Automatic CICD web app using ECR, ECS into AWS

Introduction

Deploying containerized microservices manually to Amazon ECS (Elastic Container Service) requires orchestrating multiple infrastructure components, including VPC subnets, Application Load Balancers (ALB), Target Groups, IAM Execution Roles, and Task Definitions. Consequently, this operational complexity often slows down developer velocity. AWS Copilot CLI solves this challenge by providing an opinionated abstraction layer that provisions production-ready, serverless AWS Fargate infrastructure using simple CLI commands.

In this comprehensive hands-on tutorial, we will containerize a Python Flask web service using Docker. Furthermore, we will leverage AWS Copilot to deploy our container to ECS Fargate behind an ALB, inspect live container stream logs, and establish an automated CI/CD deployment pipeline using AWS CodePipeline and GitHub.

Prerequisites

Before we dive in, ensure you have:

Step 1: Build Flask Application & Define Container Manifests

First, establish a clean directory structure and build a simple Python Flask API payload:

  • Create a project directory and build your application entrypoint file (app/app.py):
Multi Copy Code Blocks
python

from flask import Flask, jsonify
import os

app = Flask(__name__)

@app.route('/', methods=['GET'])
def health_check():
    return jsonify({
        "status": "healthy",
        "message": "Hello from AWS ECS Fargate deployed via Copilot!",
        "environment": os.getenv("COPILOT_ENVIRONMENT", "local")
    }), 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
    
  • Next, define application dependencies inside app/requirements.txt:
Multi Copy Code Blocks
plaintext
 
Flask==3.0.3
gunicorn==22.0.0
    
  • Now, create a optimized, production-grade Dockerfile inside the root directory:
Multi Copy Code Blocks
Dockerfile
 
FROM python:3.11-slim

WORKDIR /app

COPY app/requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app/ .

EXPOSE 5000

CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
    
  • Test your Docker container build locally before pushing to cloud repositories:
Multi Copy Code Blocks
Bash
 
docker build -t flask-ecs-app .
docker run -p 5000:5000 flask-ecs-app
    

Step 2: Install AWS Copilot CLI Across Platforms

Next, install the AWS Copilot binary interface onto your local execution environment:

  • macOS (Homebrew):
Multi Copy Code Blocks
Bash
 
brew install aws/tap/copilot-cli
    
  • Linux (Direct Binary Package):
Multi Copy Code Blocks
Bash
 
curl -Lo copilot https://github.com/aws/copilot-cli/releases/latest/download/copilot-linux \
&& chmod +x copilot && sudo mv copilot /usr/local/bin/
    
  • Windows (PowerShell):
Multi Copy Code Blocks
Powershell
 
Invoke-WebRequest -OutFile 'C:\copilot\copilot.exe' https://github.com/aws/copilot-cli/releases/latest/download/copilot-windows.exe
    

Step 3: Initialize Copilot App, Service, and Fargate Infrastructure

After configuring AWS CLI credentials, initialize your serverless ECS infrastructure interactively using Copilot:

  • Execute the initialization sequence inside your project root folder:
Multi Copy Code Blocks
Bash
 
copilot init
    
  • Complete the interactive command prompt responses:
    • Application Name: flask-copilot-app
    • Workload Type: Load Balanced Web Service (Deploys an ALB in front of Fargate)
    • Service Name: web
    • Dockerfile Path: ./Dockerfile
    • Port: 5000
    • Deploy to ‘test’ environment now? Select Yes
  • Consequently, Copilot will automatically build your Docker image, provision an Amazon ECR repository, create a VPC with public/private subnets, launch an ECS Cluster, configure Target Group health checks, and bind an Application Load Balancer!

Step 4: Monitor Fargate Service Status & Live Tail Logs

Once deployment finishes, Copilot outputs the live ALB DNS endpoint (e.g., [http://web-publi-123456789.ap-south-1.elb.amazonaws.com](http://web-publi-123456789.ap-south-1.elb.amazonaws.com)). Verify service health and stream runtime logs:

  • Inspect current service tasks and health metrics:
Multi Copy Code Blocks
Bash
 
copilot svc status --name web
    
  • Stream live stdout/stderr application logs directly from Fargate containers:
Multi Copy Code Blocks
Bash
 
copilot svc logs --name web --follow
    

Step 5: Configure Automated CI/CD Continuous Deployment Pipeline

Finally, establish an automated build and delivery pipeline that triggers whenever new code commits land on GitHub:

  • Initialize the pipeline manifest configuration:
Multi Copy Code Blocks
Bash
 
copilot pipeline init
    
  • Enter your GitHub repository details (github-user/repository-name) and select your tracking branch (main).
  • Commit the generated copilot/pipeline.yml and copilot/buildspec.yml manifests into Git:
Multi Copy Code Blocks
Bash
 
git add copilot/
git commit -m "feat: add Copilot CI/CD pipeline manifests"
git push -u origin main
    
  • Deploy the AWS CodePipeline infrastructure stack:
Multi Copy Code Blocks
Bash
 
copilot pipeline deploy
    
  • Consequently, any future git push to your main branch will automatically trigger AWS CodeBuild, rebuild your container image, and execute zero-downtime rolling updates on ECS Fargate!

Enterprise Container Security & Operational Best Practices:

  • Always Use Production WSGI Servers: Never execute Flask’s built-in development server (app.run()) inside Docker containers in production. Always utilize multi-threaded WSGI servers like Gunicorn or uWSGI as defined in our Dockerfile execution vector.
  • Zero-Downtime Rolling Deployments: Copilot automatically configures ECS task rolling deployments. When updating application code, new tasks are provisioned and pass health checks before old containers are drained and terminated.

Production Troubleshooting: Common Copilot & ECS Fargate Errors

Serverless container deployments rely on health checks and IAM policies. Use the diagnostic matrix below to resolve deployment issues fast:

Error 1: Task Failed Health Checks and Was Terminated

  • The Error Log (CloudWatch / Copilot Logs):
Multi Copy Code Blocks
PlainText

[ESSENTIAL] Container exited with status code 1: Task failed ALB health checks on port 5000.
    
  • The Root Cause: Gunicorn or Flask is listening on 127.0.0.1 (localhost inside container) instead of binding to 0.0.0.0 (all network interfaces), preventing the Application Load Balancer from reaching the application interface.
  • The Fix: Ensure your WSGI command or application startup binds explicitly to 0.0.0.0:5000 inside your Dockerfile and app.py.

Error 2: CannotPullContainerError During ECS Task Launch

  • The Error Log (ECS Event Stream):
Multi Copy Code Blocks
PlainText

CannotPullContainerError: Access denied to Amazon ECR repository or image tag does not exist.
    
  • The Root Cause: The ECS Task Execution IAM Role is missing required ecr:BatchGetImage or ecr:GetDownloadUrlForLayer permissions, or Fargate tasks in private subnets cannot reach ECR due to missing NAT Gateways.
  • The Fix: Ensure your Copilot environment manifest contains public subnet routing or NAT Gateways for private tasks, and verify that Copilot automatically managed the ECR resource policies during copilot init.

Error 3: Copilot Pipeline Build Fails During CodeBuild Phase

  • The Error Log (CodeBuild Log Output):
Multi Copy Code Blocks
PlainText

[Container] Phase context status code: COMMAND_EXECUTION_ERROR Message: Error building Docker image.
    
  • The Root Cause: Missing Docker build context paths or syntax errors inside the project Dockerfile when executed within the automated AWS CodeBuild environment.
  • The Fix: Run docker build -t test-build . locally to verify build health before committing manifest changes to GitHub.Multi Copy Code Blocks

Leave a Reply

Your email address will not be published. Required fields are marked *