javismiles / bear-detector-flask-deploy

Bear detector trained with fast.ai v2 and deployed with Flash, Gunicorn & Nginx to a domain name with an SSL certificate

Home Page:https://bear.volandino.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Deploying Flash + Gunicorn + Nginx + https + domain

By Javier Ideami - March 2, 2020

The jupyter notebook to train the model used by the flask app can be accessed here: Jupyter Notebook

Image of cute bear

The objective of this project is to deploy a Flask app that uses a model trained with the Fast.ai v2 library following an example in the upcoming book "Deep Learning for Coders with fastai and PyTorch: AI Applications Without a PhD" by Jeremy Howard and Sylvain Gugger.

The most important part of the project is testing a deployment process that combines a Flask app, the Gunicorn server, the Nginx server and a custom domain name with an SSL certificate, all installed on a dedicated server.

Below I explain the different deployment stages to deploy this repo combining the pieces mentioned above.

This workflow has been tested on:

Server OS: Centos 7

Name of your flask app: app

User installing this: root (you can use any other)

_________________________________________________

Install Python and nginx

If python and ningx have not been installed:

sudo yum install epel-release

sudo yum install python-pip python-devel gcc nginx

_________________________________________________

Install virtualenv

sudo pip install virtualenv

_________________________________________________

Clone our repo or create it

Create your flask app, or clone a repo where you already have it

_________________________________________________

Create a virtual environment inside the repo

virtualenv myprojectenv

source myprojectenv/bin/activate

_________________________________________________

Install flask, Gunicorn and any other dependencies

pip install gunicorn flask

Or more generally: pip install -r requirements.txt

_________________________________________________

Give instructions to the Gunicorn server to find our app

Create a wsgi entry point, file wsgi.py in the root of the repo

The file contains just this:

from app import application
if __name__ == "__main__":
    application.run()

_________________________________________________

Create a service to automatically start the gunicorn server and our app when server starts

Create a systemd unit file called app.service in /etc/systemd/system

It contains this:

[Unit]
Description=Gunicorn instance to serve my app
After=network.target

[Service]
User=root
Group=nginx
WorkingDirectory=path-to-your-app
Environment="PATH=path-to-your-app/myprojectenv/bin"
ExecStart=path-to-your-app/myprojectenv/bin/gunicorn --workers 3 --bind unix:app.sock -m 007 wsgi

[Install]
WantedBy=multi-user.target

_________________________________________________

Start the system process which will create a unix socket file in our app folder and bind to it.

sudo systemctl start app

sudo systemctl enable app

_________________________________________________

Configure nginx to proxy web requests

If you are using plesk, go to the nginx settings of the domain where you want to install the app, and select the option that makes nginx not work as a proxy of apache, so that it works standalone.

Open the nginx configuration file of your server, or of the domain where you want to put the app.

If you are using plesk, you will find the file here:

/var/www/vhosts/system/domain/conf/nginx.conf

You can add a brand new section above the standard one:

server {
    listen 80;
    server_name server_domain_or_IP;

    location / {
        proxy_set_header Host $http_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;
        proxy_pass http://unix:path-to-your-app/app.sock;
    }
}

Or you can also just add the location section to an existing server section.

This would be the beginning of a server section for the https ssl access of the domain:

server {
        listen x.x.x.x:443 ssl http2;

        server_name whatever.com;
        server_name www.whatever.com;
        server_name ipv4.whatever.com;
…………………

And this would be the beginning of a server section for the http access of the domain:

server {
        listen x.x.x.x:80;

        server_name whatever.com;
        server_name www.whatever.com;
        server_name ipv4.whatever.com;
…………………

And you could add just the location part inside one of them:

location / {
        proxy_set_header Host $http_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;
        proxy_pass http://unix:path-to-your-app/app.sock;
    }

This way you point either the root of the domain or another path within the domain to the flask app.

_________________________________________________

Give nginx permissions if necessary

If you are not using the root user, you may have to give permissions to nginx by doing:

sudo usermod -a -G user nginx

chmod 710 /home/user (or wherever the app is installed)

_________________________________________________

Test nginx conf file

Test that the syntax of your conf file changes are correct: sudo nginx -t

_________________________________________________

Launch or relaunch nginx

sudo systemctl stop nginx

sudo systemctl start nginx

sudo systemctl enable nginx

sudo systemctl status nginx

_________________________________________________

Now you can go to your domain address and access the app


Dockerizing bear app

You can dockerize your bear app.

This allows you to quickly launch it in any environment or operating system, making it truly portable.

To dockerize the app, create a Dockerfile at the root of the project:

FROM python:3

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY model ./model/
COPY resources/utils.py ./resources/
COPY *.py ./
COPY templates ./templates/

RUN mkdir resources/tmp

CMD ["gunicorn"  , "-b", "0.0.0.0:8500", "wsgi"]

Then create a docker-compose.yml file

version: '3.3'

services:
    app:
        image: javismiles/beardetector:latest
        build:
            context: .
        ports:
            - 8500:8500

Delete existing containers

docker container rm -f $(docker container ls -aq)

Build the image and launch it all at once with docker-compose

docker-compose up -d --build

At this point you can access the app on:

http://localhost:8500

Attach the app to a domain with an ssl certificate

If you want to attach the app to domain name with an ssl certificate you can do the same we did in the deployment instructions for Flask and Gunicorn, editing the nginx.conf file of the domain name you want to use.

Upload the image to your account un hub.docker.com, so that you can pull it from anywhere else and launch it anywhere else:

docker image push javismiles/beardetector:latest

You can pull the example image I created (or another that you create and upload to hub.docker.com) doing this:

docker image pull javismiles/beardetector:latest

And run it with:

docker container run -d --rm -p 8500:8500 javismiles/beardetector:latest

Then you can access it on:

http://localhost:8500

About

Bear detector trained with fast.ai v2 and deployed with Flash, Gunicorn & Nginx to a domain name with an SSL certificate

https://bear.volandino.com/

License:MIT License


Languages

Language:Jupyter Notebook 99.0%Language:Python 0.7%Language:HTML 0.3%