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:
- Scalability: Easily scale your application as traffic grows
- Reliability: AWS provides high availability and fault tolerance
- Security: Comprehensive security features to protect your application
- Flexibility: Multiple deployment options to fit your specific needs
- Cost-effective: Pay only for the resources you use
Prerequisites
Before we begin, ensure you have:
- A working Flask application
- An AWS account
- AWS CLI installed and configured
- Basic understanding of command line operations
- 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:
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):
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
- Log in to the AWS Management Console
- Navigate to EC2 Dashboard
- Click "Launch Instance"
- Select an Amazon Machine Image (AMI) - Ubuntu Server is a good choice
- Choose an instance type (t2.micro is eligible for free tier)
- Configure security groups to allow HTTP (port 80), HTTPS (port 443), and SSH (port 22)
- Create or select an existing key pair
- Launch the instance
Step 2: Connect to Your EC2 Instance
Use SSH to connect to your EC2 instance:
ssh -i /path/to/your-key.pem ubuntu@your-instance-public-dns
Step 3: Set Up the Environment
Install required software:
# 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):
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
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
):
from application import app
if __name__ == "__main__":
app.run()
Test Gunicorn:
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:
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:
sudo systemctl start flask-app
sudo systemctl enable flask-app
sudo systemctl status flask-app
Step 8: Configure Nginx
Create an Nginx server block:
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:
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
pip install awsebcli
Step 2: Initialize Elastic Beanstalk in Your Project
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
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:
eb status
Open your application in a browser:
eb open
Step 5: Update Your Application (When Needed)
After making changes to your code:
# 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:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: application:application
aws:elasticbeanstalk:application:environment:
PYTHONPATH: "/var/app/current:$PYTHONPATH"
Best Practices for Flask on AWS
- Use Environment Variables: Store configuration in environment variables rather than hardcoding values.
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')
- Implement Logging: Set up proper logging for your Flask application:
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)
-
Use a CDN for Static Content: Configure AWS CloudFront for serving static assets.
-
Database Considerations: Use Amazon RDS instead of SQLite for production applications.
-
HTTPS: Enable HTTPS using AWS Certificate Manager and configure your load balancer.
-
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:
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:
- Add these files to requirements.txt:
flask==2.0.1
gunicorn==20.1.0
flask-sqlalchemy==2.5.1
pymysql==1.0.2
- Create
.ebextensions/01_flask.config
:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: application:application
aws:elasticbeanstalk:application:environment:
FLASK_ENV: production
- Create
.ebextensions/02_db_setup.config
to create an RDS instance:
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
- 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:
- Manual deployment to EC2 instances, which offers full control over your environment
- 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
- AWS Documentation for Python Applications
- Flask Documentation
- Gunicorn Documentation
- AWS Well-Architected Framework
Exercises
- Deploy a simple "Hello World" Flask application to AWS EC2.
- Modify the blog example to use Amazon S3 for storing uploaded images.
- Set up a CI/CD pipeline using AWS CodePipeline to automatically deploy your Flask application when you push to GitHub.
- Configure HTTPS for your Flask application using AWS Certificate Manager.
- 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! :)