[PYTHON] I tried running Flask on Raspberry Pi 3 Model B + using Nginx and uWSGI

background purpose

I knew that uWSGI would be used to deploy a Python-implemented application to a production environment, but I didn't know why or how to use it. So, let's run it on Raspberry Pi 3 Model B + using Nginx, uWSGI, Python + Flask.

In the first place, WSGI is an abbreviation for Web Server Gateway Interface. As described in Abstruct of PEP 3333, it is an interface that connects a web server and a Python application, and enhances the portability of the web application between various web servers.

This document specifies a proposed standard interface between web servers and Python web applications or frameworks, to promote web application portability across a variety of web servers.

Deploy the application created by Python + Flask using uWSGI of WSGI application container that conforms to this WSGI.

Implementation

The order of implementation is as follows.

  1. Run Flask applications in your development environment
  2. Run Flask applications with uWSGI
  3. Set Nginx and hit the Raspberry Pi IP from the browser
  4. Automatically start uWSGI

Run Flask applications in your development environment

First, the directory of the development environment is as follows.

$ tree
.
├── README.md
├── conf
│   └── uwsgi.ini
├── requirements.txt
└── src
    └── main.py

The required libraries are listed in requirements.txt. You can use it to install the library with pip install -r requirements.txt.

$ cat requirements.txt 
flask
isort
flake8
ipython
uwsgi

src / main.py is:

$ cat src/main.py 
from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

You can see that the development server is started on port 5000 with python src / main.py and the application is actually running.

Run Flask applications with uWSGI

When actually operating the application, it is necessary to make various settings. For example, the output destination of the socket, the number of processes, the number of threads, and the like can be mentioned. Since it is troublesome to specify these settings in combination with the uwsgi command options, the options are summarized in the following uwsgi.ini file.

Then you can check if the application is actually running with ʻuwsgi --ini uwsgi.ini`.

$ cat conf/uwsgi.ini
[uwsgi]
wsgi-file = ../src/main.py
; module = main
callable = app
chmod-socket = 666
socket = /tmp/%n.sock
;http = 0.0.0.0:8080
;daemonize = /var/log/uwsgi/flask/%n.log
;pidfile = /tmp/app.pid
;harakiri = 600

Set Nginx and hit the Raspberry Pi IP from the browser

After accessing Nginx port 80 with an HTTP request, proxy to uWSGI using UNIX domain socket. The settings on the Nginx side are as follows.

server {
    listen 80;
    #Reverse proxy to Flask app when accessing port 80
    #This way you don't waste ports
    location / {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
    proxy_set_header  Host                $host;
    proxy_set_header  X-Forwarded-For     $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Host    $host;
    proxy_http_version      1.1;
    proxy_connect_timeout 600;
    proxy_read_timeout    600;
    proxy_send_timeout    600;
    send_timeout          600;
    uwsgi_read_timeout    600;
}

By the way, a UNIX domain socket is a socket for interprocess communication running on the same machine. Therefore, it cannot communicate with other machines. On the other hand, a socket that communicates with other machines via a network by relying on IP and port number is called an INET domain socket. UNIX domain sockets can only communicate with processes on the same machine, but they are faster than INET domain sockets.

Automatically start uWSGI

There are several ways to daemonize uWSGI. The first is to add the daemonize option to the uwsgi command options. The second method is to register uWSGI in systemctl and make it start automatically. The second one was adopted in this implementation.

--Creating a service (/etc/systemd/system/app.service)

[Unit]
Description=uWSGI instance to serve myapp
After=network.target

[Service]
;User==www-data
Group=www-data
WorkingDirectory=/home/pi/WorkSpace/DeployFlask/conf
ExecStart=/home/pi/.pyenv/shims/uwsgi --ini /home/pi/WorkSpace/DeployFlask/conf/uwsgi.ini

[Install]
WantedBy=multi-user.target

--Starting the service

$ sudo systemctl start app

--Service auto-start settings

$ sudo systemctl enable app

--Understanding the service status

$ sudo systemctl status app
● app.service - uWSGI instance to serve myapp
   Loaded: loaded (/etc/systemd/system/app.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2020-05-12 18:22:25 JST; 7min ago
 Main PID: 2615 (uwsgi)
    Tasks: 1 (limit: 2200)
   Memory: 10.9M
   CGroup: /system.slice/app.service
           └─2615 /home/pi/.pyenv/versions/DeployFlask/bin/uwsgi --ini /home/pi/WorkSpace/DeployFlask/conf/uwsgi.ini

Clogged things / issues

--Since daemonize = /var/log/uwsgi/flask/%n.log was described in the uwsgi.ini file, the server itself returned 502 after a certain period of time. It was the first method I took to make uwsgi a daemon, but I deleted it because the description was bad.

reference

Deploy

article

-Introduction to uWSGI -Note that I got a timeout error many times after starting uWSGI from systemd

Socket communication

-I can't sleep without checking! The story of the socket that I couldn't sleep anymore

Recommended Posts

I tried running Flask on Raspberry Pi 3 Model B + using Nginx and uWSGI
USB boot on Raspberry Pi 4 Model B
[Python] I tried running a local server using flask
raspberry pi 1 model b, python
I tried running Movidius NCS with python of Raspberry Pi3
I tried connecting Raspberry Pi and conect + with Web API
I tried using the DS18B20 temperature sensor with Raspberry Pi
I tried to automate [a certain task] using Raspberry Pi
raspberry pi 1 model b, node-red part 17
MQTT on Raspberry Pi and Mac
Try using ArUco on Raspberry Pi
Weighing instrument using raspberry pi and hx711 (GUI display on Tkinter)
Detect "brightness" using python on Raspberry Pi 3!
Run servomotor on Raspberry Pi 3 using python
Initial settings for using GrovePi + starter kit and camera on Raspberry Pi
I tried hosting Pytorch's deep learning model using TorchServe on Amazon SageMaker
Build OpenCV-Python environment on Raspberry Pi B +
Detect temperature using python on Raspberry Pi 3!
Start a web server using Bottle and Flask (I also tried using Apache)
I installed OpenCV-Python on my Raspberry Pi
[Raspberry Pi] Publish a web application on https using Apache + WSGI + Python Flask
I made an image classification model and tried to move it on mobile
I tried using PyEZ and JSNAPy. Part 1: Overview
I tried using Remote API on GAE / J
I tried web scraping using python and selenium
Detect slide switches using python on Raspberry Pi 3!
Try using a QR code on a Raspberry Pi
I tried L-Chika with Raspberry Pi 4 (Python edition)
[Pythonocc] I tried using CAD on jupyter notebook
Sound the buzzer using python on Raspberry Pi 3!
Introduced Ceph on Kubernetes on Raspberry Pi 4B (ARM64)
Install PyCall on Raspberry PI and try using GPIO's library for Python from Ruby
From installing Flask on CentOS to making it a service with Nginx and uWSGI
Record temperature and humidity with systemd on Raspberry Pi
Build an OpenCV4 environment on Raspberry Pi using Poetry
Create a color sensor using a Raspberry Pi and a camera
I tried running the app on the IoT platform "Rimotte"
I tried hosting a Pytorch sample model using TorchServe
Try using the temperature sensor (LM75B) on the Raspberry Pi.
Communication between uWSGI and Nginx using Unix Domain Socket
Ubuntu 20.04 on raspberry pi 4 with OpenCV and use with python
[MNIST] I tried Fine Tuning using the ImageNet model.
I tried using PySpark from Jupyter 4.x on EMR
USB boot with Raspberry Pi 4 Model B (3) LVM edition
Installation of Docker on Raspberry Pi and L Chika
Install pyenv on Raspberry Pi and version control Python
Output to "7-segment LED" using python on Raspberry Pi 3!
Troubleshoot with installing OpenCV on Raspberry Pi and capturing
PyTorch Learning Note 2 (I tried using a pre-trained model)
I tried to install scrapy on Anaconda and couldn't
Input and output display images directly using the frame buffer (/ dev / fb0) on Raspberry Pi
I wanted to run the motor with Raspberry Pi, so I tried using Waveshare's Motor Driver Board
I tried using the Pi Console I / F of the Raspberry Pi IoT starter kit "anyPi" from Mechatrax.
I tried to make a motion detection surveillance camera with OpenCV using a WEB camera with Raspberry Pi
I tried using PI Fu to generate a 3D model of a person from one image
I tried using parameterized
I tried using argparse
I tried using mimesis
I tried using anytree
I tried running pymc
I tried using Summpy