How to deploy a Python app to AWS EC2 via SSH
After you built up a Python app locally, it is time for you to upload to cloud, which is called deploy. Here are the steps to deploy your python code on AWS EC2.
Usually, there is a venv in your local python file. You don’t need to upload it to cloud. Instead, you can extract the venv to requirments.txt, upload it to cloud and then rebuild the venv in the cloud by this file.
by the way, you can exclude any files that you don’t want to upload in your python directory:
rsync -av --exclude='.git/' --exclude='.DS_Store' --exclude='venv_winjob' --exclude='__pycache__' --exclude='.gitattributes' --exclude='.gitignore' -e "ssh -i /Users/henrywu/MyDrive/98_Products/P01-Project-Alpha/03-keys/AWS_EC2_key_pair_helloworld.pem" /Users/henrywu/MyDrive/99_Coding/01-Github/winjob/ ec2-user@ec2-44-239-28-119.us-west-2.compute.amazonaws.com:/home/ec2-user/firstweb/
rsync -av \
--exclude='.git/' \
--exclude='.DS_Store' \
--exclude='venv_winjob' \
--exclude='__pycache__' \
--exclude='.gitattributes' \
--exclude='.gitignore' \
-e "ssh -i /Users/henrywu/MyDrive/98_Products/config/AWS_EC2_key_pair_winjob.pem" \
/Users/henrywu/MyDrive/99_Coding/01-Github/winjob/ \
ec2-user@ec2-54-185-22-17.us-west-2.compute.amazonaws.com:/home/ec2-user/winjob/
Note: please pay attention to the prompt of the terminal. when upload code from local to AWS, the prompt should be local computer. When set up the environment in AWS, we should login SSH, and the prompt should be user in AWS.
You can use ls
command to check if the upload is successful:
After login SSH, we can set up the environment on EC2.
sudo nano /etc/nginx/conf.d/firstweb.conf
# HTTP server block
server {
listen 80;
listen [::]:80;
server_name winjob.ai www.winjob.ai;
location ^~ /.well-known/acme-challenge/ {
root /home/ec2-user/firstweb; # This directory must be the root of your web content for the ACME challenge
allow all; # No restrictions for accessing this location
try_files $uri =404; # Serve files if present, or error
}
location / {
# Ensure that requests to the application root URL are proxied to Gunicorn
proxy_pass http://localhost:5000;
# Include proxy headers for forwarding the original host, IP, and protocol used
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Define the max body size for client requests, if needed
client_max_body_size 10M; # Adjust the size as necessary
}
# ... rest of your server block ...
}
[Unit]
Description=Gunicorn instance to serve firstweb
After=network.target
[Service]
User=ec2-user
Group=nginx
WorkingDirectory=/home/ec2-user/firstweb
Environment="PATH=/home/ec2-user/firstweb/venv_winjob/bin"
ExecStart=/home/ec2-user/firstweb/venv_winjob/bin/gunicorn --workers 3 --bind 0.0.0.0:5000 app:app
[Install]
WantedBy=multi-user.target
Restart=on-failure
RestartSec=5s
sudo systemctl reload nginx
sudo systemctl restart nginx
sudo systemctl daemon-reload
sudo systemctl restart firstweb.service
run the code
first, activate the venv, then run the code:
gunicorn --workers 3 --bind 0.0.0.0:5000 app:app
Basically, there are two config files the most important:
nginx
sudo nano /etc/nginx/conf.d/firstweb.conf
# HTTP server block
server {
listen 80;
listen [::]:80;
server_name winjob.ai www.winjob.ai;
location ^~ /.well-known/acme-challenge/ {
root /home/ec2-user/firstweb; # This directory must be the root of your web content for the ACME challenge
allow all; # No restrictions for accessing this location
try_files $uri =404; # Serve files if present, or error
}
location / {
# Ensure that requests to the application root URL are proxied to Gunicorn
proxy_pass http://localhost:5000;
# Include proxy headers for forwarding the original host, IP, and protocol used
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Define the max body size for client requests, if needed
client_max_body_size 10M; # Adjust the size as necessary
}
# ... rest of your server block ...
}
gunicorn
sudo nano /etc/systemd/system/firstweb.service
[Unit]
Description=Gunicorn instance to serve firstweb
After=network.target
[Service]
User=ec2-user
Group=nginx
WorkingDirectory=/home/ec2-user/firstweb
Environment="PATH=/home/ec2-user/firstweb/venv_winjob/bin"
ExecStart=/home/ec2-user/firstweb/venv_winjob/bin/gunicorn --workers 3 --bind unix:/home/ec2-user/firstweb/firstweb.sock app:app
[Install]
WantedBy=multi-user.target