DEV Community

Cover image for Deploying Flask App in Digital Ocean Droplet
Eddie Gulay
Eddie Gulay

Posted on

Deploying Flask App in Digital Ocean Droplet

to production with flask in a 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

  1. Creating digital ocean droplet
  2. Preparing environment
  3. 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
Enter fullscreen mode Exit fullscreen mode

ssh init

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Create a directory for your project and navigate to it.

mkdir apps
cd apps
Enter fullscreen mode Exit fullscreen mode

Create a virtual environment

python3 -m venv venv
Enter fullscreen mode Exit fullscreen mode

Activate the virtual environment

source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Clone your project

let's call our project flask_app

git clone your_project_url.git
cd flask_app
Enter fullscreen mode Exit fullscreen mode

Install project dependencies

pip install -r flask_app/requirements.txt
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

run the app

python app.py
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Configure Gunicorn

Safe check if gunicorn is installed

gunicorn --version
Enter fullscreen mode Exit fullscreen mode

if not installed install it using pip

pip install gunicorn
Enter fullscreen mode Exit fullscreen mode

try running your app using gunicorn

gunicorn --bind 0.0.0.0:5000 wsgi:app
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Then create a file called flask_app.service in /etc/systemd/system/ directory.

sudo nano /etc/systemd/system/flask_app.service
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Check the status of the service to make sure it's running without any issues.

sudo systemctl status flask_app
Enter fullscreen mode Exit fullscreen mode

example output
alt text

Configure Nginx to Proxy Requests

Install Nginx

sudo apt install nginx
Enter fullscreen mode Exit fullscreen mode

Create a new server block configuration file in Nginx's sites-available directory.

sudo nano /etc/nginx/sites-available/flask_app
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Test your Nginx configuration for syntax errors.

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

If the test is successful, restart Nginx.

sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

Remember we allowed port 5000 earlier, now we can remove it.

sudo ufw delete allow 5000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Obtain a free SSL certificate for your domain using certbot if you have a domain.

sudo certbot --nginx -d your_domain_or_ip
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Create a new server block configuration file in Nginx's sites-available directory.

sudo nano /etc/nginx/sites-available/flask_app
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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 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. ✨

Top comments (0)