Deploying Flask App in Digital Ocean Droplet
Recently, I read a blog post about customizing APIs from Gemini Models, but when I tried following the instructions, everything got stuck at localhost:5000. Basically, my apps were only visible on my computer. So, I went on a quest to figure out how to make it accessible to everyone. That's when I learned about deploying Flask apps on a Digital Ocean droplet. This guide is like a map to help you do the same, so your projects don't get stuck at localhost:5000 either. Let's share your awesome creations with the world! ✨ It's time to unleash them onto the global stage by mastering the art of deploying Flask applications on a Digital Ocean droplet or any Ubuntu Server.
Step by step guide to deploying Flask app in digital ocean droplet using gunicorn and nginx.
Things we are going to cover
- Creating digital ocean droplet
- Preparing environment
- Actual deployment guide
Creating digital ocean droplet
Go to digital ocean and create an account if you don't have one. here is the link
✨ Digital Ocean 🎉 ~ This is a referral link, you will get $200 credit for 60 days. so no more excuses to why your projects are not deployed.
After creating an account, click on the create button and select droplets. You will be presented with a list of options. Select the Ubuntu 20.04 LTS. Choose the plan of your preference. You can choose any data center region you want. I usually choose the one closest to me.
Choose the authentication method. SSH keys are the best but for this guide, we are going to use a password. You can always add SSH keys later.
if you are a windows user get yourself a virtual box and install Ubuntu. or use WSL 😂.
Preparing environment
Now that we have our droplet up and running, let's prepare our environment.
connect to your droplet using ssh.
ssh root@your_droplet_ip
Provide your password and you are in.
Update and upgrade
sudo apt update
sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools
the command sudo apt update refreshes the list of available software packages on your system, ensuring that it has the latest information from the repositories. Following that, sudo apt install python3-pip python3-dev build-essential libssl-dev libffi-dev python3-setuptools installs essential tools and dependencies for Python development. This includes the Python 3 package manager (python3-pip), development headers for Python (python3-dev), fundamental build tools (build-essential), as well as libraries for SSL and FFI (libssl-dev and libffi-dev), and the Python package distribution tools (python3-setuptools).
Create a virtual environment
sudo apt install python3-venv
Create a directory for your project and navigate to it.
mkdir apps
cd apps
Create a virtual environment
python3 -m venv venv
Activate the virtual environment
source venv/bin/activate
Clone your project
let's call our project flask_app
git clone your_project_url.git
cd flask_app
Install project dependencies
pip install -r flask_app/requirements.txt
now that we have your project up and running, let's run it and see if everything is working as expected.
first lets allow the port we are going to use.
sudo ufw allow 5000
run the app
python app.py
if everything is working as expected, you should be able to access your app using your droplet ip and port 5000.
something like this http://your_droplet_ip:5000
Actual deployment guide
Create WSGI entry point
Create a file called wsgi.py
in your project root directory.
or just copy app.py to wsgi.py
cp app.py wsgi.py
Configure Gunicorn
Safe check if gunicorn is installed
gunicorn --version
if not installed install it using pip
pip install gunicorn
try running your app using gunicorn
gunicorn --bind 0.0.0.0:5000 wsgi:app
Check your app using your droplet ip and port 5000. something like this http://your_droplet_ip:5000
if everything is working as expected, let's move to the next step.
Create a systemd service file
Create a systemd service file for gunicorn, this will allow gunicorn to automatically start on boot.
first deactivate your virtual environment
deactivate
Then create a file called flask_app.service
in /etc/systemd/system/
directory.
sudo nano /etc/systemd/system/flask_app.service
Add the following configuration to the file
[Unit]
Description=Gunicorn instance to serve flask_app
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=/root/apps/flask_app
Environment="PATH=/root/apps/venv/bin"
ExecStart=/root/apps/venv/bin/gunicorn --workers 3 --bind 0.0.0.0:5000 -m 777 wsgi:app
[Install]
WantedBy=multi-user.target
After creating the file, start the gunicorn service and enable it to start on boot.
sudo systemctl start flask_app
sudo systemctl enable flask_app
Check the status of the service to make sure it's running without any issues.
sudo systemctl status flask_app
example output
Configure Nginx to Proxy Requests
Install Nginx
sudo apt install nginx
Create a new server block configuration file in Nginx's sites-available
directory.
sudo nano /etc/nginx/sites-available/flask_app
Add the following configuration to the file. Replace your_domain_or_ip
with your actual domain name or IP address.
server {
listen 80;
server_name 143.198.232.28;
location / {
proxy_pass https://143.198.232.28:5000;
}
}
Create a symbolic link to the file in the sites-enabled
directory.
sudo ln -s /etc/nginx/sites-available/flask-app /etc/nginx/sites-enabled
Test your Nginx configuration for syntax errors.
sudo nginx -t
you should see something like this
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
If the test is successful, restart Nginx.
sudo systemctl restart nginx
Remember we allowed port 5000 earlier, now we can remove it.
sudo ufw delete allow 5000
Now you should be able to access your app using your domain name or IP address without the port number. something like this http://your_droplet_ip
Secure your app with SSL
Install certbot
sudo apt install certbot python3-certbot-nginx
Obtain a free SSL certificate for your domain using certbot if you have a domain.
sudo certbot --nginx -d your_domain_or_ip
Certbot will ask you to provide an email address for lost key recovery and notices, and to agree to the terms of service. After doing so, certbot will communicate with the Let's Encrypt server, then run a challenge to verify that you control the domain you're requesting a certificate for.
When that's finished, certbot will ask how you'd like to configure your HTTPS settings.
or you can use openssl to generate a self-signed certificate.
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/flask_app.key -out /etc/ssl/certs/flask_app.crt
Create a new server block configuration file in Nginx's sites-available
directory.
sudo nano /etc/nginx/sites-available/flask_app
Add the following configuration to the file. Replace your_domain_or_ip
with your actual domain name or IP address.
server {
listen 80;
server_name
location / {
proxy_pass https://your_domain_or_ip;
}
}
server {
listen 443 ssl;
server_name your_domain_or_ip;
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
location / {
proxy_pass https://your_domain_or_ip;
}
}
This configuration tells Nginx to listen on both port 80 (HTTP) and port 443 (HTTPS). It uses the self-signed certificate and private key that you created.
After updating the Nginx configuration, remember to test the configuration and reload or restart Nginx:
sudo nginx -t
sudo systemctl reload nginx
The nginx -t
command checks the configuration for syntax errors. The systemctl reload nginx
command reloads the Nginx configuration without interrupting currently connected clients.
Please note that because the certificate is self-signed, browsers will show a warning to users that the site is not secure. Users will need to manually accept the risk and proceed to the site.
Conclusion
Hopefully with this template guide, you were able to deploy your flask app in a digital ocean droplet. Your projects are way too precious to be running on localhost. Deploy them and share them with the world. If you have any questions or suggestions, feel free to reach out help is everywhere. ✨