Skip to main content

Flask AWS Deployment

Introduction

Deploying Flask applications to Amazon Web Services (AWS) provides a scalable, reliable, and professional hosting solution for your web applications. AWS offers various services that can accommodate Flask applications of different sizes and complexities. In this guide, we'll explore how to deploy a Flask application to AWS, focusing on the most common approaches: using EC2 instances and Elastic Beanstalk.

By the end of this tutorial, you'll understand:

  • Why AWS is a popular choice for Flask deployment
  • How to prepare your Flask application for AWS deployment
  • Step-by-step deployment to AWS EC2
  • Deploying with AWS Elastic Beanstalk
  • Best practices for Flask applications in production on AWS

Why Choose AWS for Flask Deployment?

AWS offers several advantages for hosting Flask applications:

  1. Scalability: Easily scale your application as traffic grows
  2. Reliability: AWS provides high availability and fault tolerance
  3. Security: Comprehensive security features to protect your application
  4. Flexibility: Multiple deployment options to fit your specific needs
  5. Cost-effective: Pay only for the resources you use

Prerequisites

Before we begin, ensure you have:

  1. A working Flask application
  2. An AWS account
  3. AWS CLI installed and configured
  4. Basic understanding of command line operations
  5. Python and pip installed

Preparing Your Flask Application for AWS

Before deploying to AWS, we need to make some adjustments to our Flask application to make it production-ready.

1. Project Structure

A well-organized project structure is essential. Here's a recommended structure:

my_flask_app/
├── application.py
├── requirements.txt
├── .ebignore
├── static/
│ ├── css/
│ ├── js/
│ └── images/
└── templates/
└── index.html

2. Create a requirements.txt file

Generate a requirements.txt file to list all dependencies:

bash
pip freeze > requirements.txt

Ensure your file includes at least:

flask==2.0.1
gunicorn==20.1.0

3. Configure your application for production

Modify your main application file (we'll name it application.py as AWS Elastic Beanstalk looks for this by default):

python
from flask import Flask, render_template

application = Flask(__name__)
# AWS Elastic Beanstalk expects the application to be named 'application'
# Create an alias for compatibility with local development
app = application

@app.route('/')
def home():
return render_template('index.html')

if __name__ == '__main__':
# For local development
app.run(debug=True)
# In production, Gunicorn will run this application

Deploying to AWS EC2

Amazon EC2 (Elastic Compute Cloud) provides virtual servers where you can deploy your Flask application with full control over the environment.

Step 1: Launch an EC2 Instance

  1. Log in to the AWS Management Console
  2. Navigate to EC2 Dashboard
  3. Click "Launch Instance"
  4. Select an Amazon Machine Image (AMI) - Ubuntu Server is a good choice
  5. Choose an instance type (t2.micro is eligible for free tier)
  6. Configure security groups to allow HTTP (port 80), HTTPS (port 443), and SSH (port 22)
  7. Create or select an existing key pair
  8. Launch the instance

Step 2: Connect to Your EC2 Instance

Use SSH to connect to your EC2 instance:

bash
ssh -i /path/to/your-key.pem ubuntu@your-instance-public-dns

Step 3: Set Up the Environment

Install required software:

bash
# Update package lists
sudo apt-get update

# Install Python and pip
sudo apt-get install python3 python3-pip

# Install Nginx web server
sudo apt-get install nginx

# Install virtual environment
sudo apt-get install python3-venv

Step 4: Clone Your Application

Create a directory for your application and clone it (or transfer files):

bash
mkdir ~/myflaskapp
cd ~/myflaskapp

# If using Git
git clone https://github.com/yourusername/your-flask-repo.git .

# Or manually transfer files using SCP

Step 5: Set Up a Virtual Environment

bash
python3 -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt

# Install Gunicorn if not in requirements.txt
pip install gunicorn

Step 6: Configure Gunicorn

Create a WSGI entry point (wsgi.py):

python
from application import app

if __name__ == "__main__":
app.run()

Test Gunicorn:

bash
gunicorn --bind 0.0.0.0:8000 wsgi:app

Step 7: Create a Systemd Service File

Create a service file to manage your Gunicorn process:

bash
sudo nano /etc/systemd/system/flask-app.service

Add the following content:

[Unit]
Description=Gunicorn instance to serve Flask application
After=network.target

[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/myflaskapp
Environment="PATH=/home/ubuntu/myflaskapp/venv/bin"
ExecStart=/home/ubuntu/myflaskapp/venv/bin/gunicorn --workers 3 --bind unix:myflaskapp.sock -m 007 wsgi:app

[Install]
WantedBy=multi-user.target

Enable and start the service:

bash
sudo systemctl start flask-app
sudo systemctl enable flask-app
sudo systemctl status flask-app

Step 8: Configure Nginx

Create an Nginx server block:

bash
sudo nano /etc/nginx/sites-available/myflaskapp

Add the configuration:

server {
listen 80;
server_name your_domain_or_ip;

location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/myflaskapp/myflaskapp.sock;
}
}

Enable the site and restart Nginx:

bash
sudo ln -s /etc/nginx/sites-available/myflaskapp /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx

You should now be able to access your Flask application by visiting your EC2 instance's public IP address or domain name!

Deploying with AWS Elastic Beanstalk

Elastic Beanstalk provides an easier way to deploy and manage your applications on AWS.

Step 1: Install the Elastic Beanstalk CLI

bash
pip install awsebcli

Step 2: Initialize Elastic Beanstalk in Your Project

bash
cd your-flask-app
eb init

Follow the prompts to:

  • Select a region
  • Create a new application
  • Select Python as the platform
  • Choose to use AWS CodeCommit (optional)
  • Set up SSH for instances (recommended)

Step 3: Create an Environment

bash
eb create flask-env

This creates a new environment called "flask-env" and deploys your application.

Step 4: Verify the Deployment

Check the deployment status:

bash
eb status

Open your application in a browser:

bash
eb open

Step 5: Update Your Application (When Needed)

After making changes to your code:

bash
# Commit changes first if using Git
git add .
git commit -m "Update application"

# Deploy the updates
eb deploy

Common Configuration: WSGI

Create a file named .ebextensions/python.config in your project directory:

yaml
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: application:application
aws:elasticbeanstalk:application:environment:
PYTHONPATH: "/var/app/current:$PYTHONPATH"

Best Practices for Flask on AWS

  1. Use Environment Variables: Store configuration in environment variables rather than hardcoding values.
python
import os

app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'default-dev-key')
app.config['DATABASE_URI'] = os.environ.get('DATABASE_URI', 'sqlite:///dev.db')
  1. Implement Logging: Set up proper logging for your Flask application:
python
import logging
from logging.handlers import RotatingFileHandler

if __name__ != '__main__':
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
else:
handler = RotatingFileHandler('app.log', maxBytes=10000, backupCount=3)
handler.setLevel(logging.INFO)
app.logger.addHandler(handler)
  1. Use a CDN for Static Content: Configure AWS CloudFront for serving static assets.

  2. Database Considerations: Use Amazon RDS instead of SQLite for production applications.

  3. HTTPS: Enable HTTPS using AWS Certificate Manager and configure your load balancer.

  4. Monitoring: Set up AWS CloudWatch for monitoring your application.

Real-World Example: Flask Blog with AWS Deployment

Let's create a simple blog application and deploy it to AWS. Here's the basic structure:

python
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
import os

application = Flask(__name__)
app = application

# Configure database
if 'RDS_HOSTNAME' in os.environ:
# Running on AWS
SQLALCHEMY_DATABASE_URI = f"mysql+pymysql://{os.environ['RDS_USERNAME']}:{os.environ['RDS_PASSWORD']}@{os.environ['RDS_HOSTNAME']}:{os.environ['RDS_PORT']}/{os.environ['RDS_DB_NAME']}"
else:
# Local development
SQLALCHEMY_DATABASE_URI = "sqlite:///blog.db"

app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)

@app.route('/')
def home():
posts = Post.query.all()
return render_template('index.html', posts=posts)

@app.route('/post/<int:post_id>')
def post(post_id):
post = Post.query.get_or_404(post_id)
return render_template('post.html', post=post)

@app.route('/create', methods=['GET', 'POST'])
def create():
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
new_post = Post(title=title, content=content)
db.session.add(new_post)
db.session.commit()
return redirect(url_for('home'))
return render_template('create.html')

if __name__ == '__main__':
db.create_all()
app.run(debug=True)

For AWS Elastic Beanstalk deployment:

  1. Add these files to requirements.txt:
flask==2.0.1
gunicorn==20.1.0
flask-sqlalchemy==2.5.1
pymysql==1.0.2
  1. Create .ebextensions/01_flask.config:
yaml
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: application:application
aws:elasticbeanstalk:application:environment:
FLASK_ENV: production
  1. Create .ebextensions/02_db_setup.config to create an RDS instance:
yaml
Resources:
AWSEBRDSDatabase:
Type: AWS::RDS::DBInstance
Properties:
AllocatedStorage: 5
DBInstanceClass: db.t2.micro
DBName: ebdb
Engine: mysql
EngineVersion: 8.0
MasterUsername: "admin"
MasterUserPassword: "password" # Use AWS Secrets Manager in real applications
MultiAZ: false
  1. Deploy with eb create flask-blog-env

Summary

In this guide, you've learned how to deploy Flask applications to AWS using two common approaches:

  1. Manual deployment to EC2 instances, which offers full control over your environment
  2. Simplified deployment with Elastic Beanstalk, which abstracts away much of the infrastructure management

We've covered the essential steps for preparing your Flask application for production, configuring servers, and implementing best practices for AWS deployment. By following these steps, you can create a robust, scalable hosting solution for your Flask web applications.

Additional Resources

  1. AWS Documentation for Python Applications
  2. Flask Documentation
  3. Gunicorn Documentation
  4. AWS Well-Architected Framework

Exercises

  1. Deploy a simple "Hello World" Flask application to AWS EC2.
  2. Modify the blog example to use Amazon S3 for storing uploaded images.
  3. Set up a CI/CD pipeline using AWS CodePipeline to automatically deploy your Flask application when you push to GitHub.
  4. Configure HTTPS for your Flask application using AWS Certificate Manager.
  5. Implement monitoring for your Flask application using AWS CloudWatch.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)