Run Python web apps on NGINX + NGINX Unit + Flask

Python web application development with NGINX + NGINX Unit + Flask

I wanted to develop a web with Python, so I built an environment for a Python web application. Until now, the mainstream configuration was NGINX <-> uwsgi <-> Flask, but in April 2018 NGINX released the lightweight AP server NGINX Unit. This time, we will use NGINX Unit and build a web application environment with the configuration NGINX <-> NGINX Unit <-> Flask.

environment

Use NGINX as the web server, NGINX Unit as the AP server, and Flask as the Python web framework.

Remarks

The server uses a virtual environment of Vagrant and VirtualBox. Please enable the private network.

$ vagrant init centos/7
$ vi Vagrantfile
- # config.vm.network "private_network", ip: "192.168.33.10"
+ config.vm.network "private_network", ip: "192.168.33.10"
$ vagrant up
$ vagrant ssh

Connect to the virtual environment with vagrant ssh and disable selinux.

$ sudo vi /etc/selinux/config
- SELINUX=enforcing
+ SELINUX=disabled
$ sudo reboot

Python development environment construction

Build a Python development environment in a virtual environment. By default, CentOS has Python 2.7.5 installed.

$ python --version
Python 2.7.5

This time we will use Python 3.7.4.

Install Python3 on CentOS

Install Python on CentOS by referring to the procedure on the Python Official Page. First, install the necessary tools.

$ sudo yum -y groupinstall "development tools"
$ sudo yum install -y bzip2-devel gdbm-devel libffi-devel libuuid-devel ncurses-devel openssl-devel readline-devel sqlite-devel tk-devel wget xz-devel zlib-devel

Download the installer from Python's Official Page (https://www.python.org/downloads/release/python-374/) with wget. Unzip after downloading.

$ wget https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz
$ tar xzf Python-3.7.4.tgz

Build after unzipping the source code.

$ cd Python-3.7.4
$ ./configure --enable-shared
$ make
$ sudo make install
$ sudo sh -c "echo '/usr/local/lib' > /etc/ld.so.conf.d/custom_python3.conf"
$ sudo ldconfig

The built command will be installed under / usr / local / bin.

$ which python
/usr/bin/python
$ which python3
/usr/local/bin/python3
$ python3 --version
Python 3.7.4
$ which pip3
/usr/local/bin/pip3

Finally upgrade pip.

$ pip3 install --upgrade pip --user

The latest version of the pip command will be installed on your local bin.

$ which pip
~/.local/bin/pip
$ pip --version
pip 19.2.3 from /home/vagrant/.local/lib/python3.7/site-packages/pip (python 3.7)

That's all for building the Python environment.

Creating a Python virtual environment

Build a Python virtual environment to switch and manage packages for each project. Python provides venv as a standard module that supports the creation of virtual environments. Create a virtual environment using venv.

# flask_Create a virtual environment called sample
$ python3 -m venv flask_sample
$ ls
venv

Enable the virtual environment created by venv.

$ source flask_sample/bin/activate
(flask_sample)$

You can activate the virtual environment by running the ʻactivate script in the directory created by the venvmodule. When you enable the virtual environment,(virtual environment name)` is displayed at the beginning of the prompt. Go to the directory of the virtual environment you created and check the configuration.

(flask_sample)$ cd flask_sample
(flask_sample)$ ls
bin  include  lib  lib64  pyvenv.cfg

The bin directory contains the ʻactivate script that activates the virtual environment and the Python package management tool pipcommand. When you run thepipcommand in a virtual environment, the commands in this directory are run. The installed packages will be installed inlib / python3.7 / site-packages and lib64 / python3.7 / site-packages. In a virtual environment, ignore the site-packages` directory in Python itself and use the packages in this directory. You can develop apps without polluting the package of Python itself.

Creating a sample project in Flask

Flask is a small Python micro-framework. The features listed as standard are minimal and are used when developing small applications. Plugins are provided so you can extend your functionality. Use Django if you want to develop a large application from the beginning.

Flask installation

Install Flask in the venv virtual environment.

(flask_sample)$  pip install Flask

Creating an application

The structure of the sample project is as follows.

/sample
  |- app.py
  |- templates
        |- index.html
        |- post.html

Each code is implemented as follows.

app.py


from flask import Flask ,render_template,request

application = Flask(__name__)

@application.route('/')
def index():
    return render_template('index.html')

@application.route('/sample',methods=['POST'])
def sample():
    message = request.form['message']
    return render_template('post.html',message=message)

if __name__=="__main__":
    application.run(host='0.0.0.0')

index.html


<html>
  <head>
    <meta charset="utf-8" />
    <title>Flask Sample</title>
  </head>
  <body>
    <h1>Flask Smaple</h1>
    <form action="sample" method="post">
      <input type="text" name="message" />
      <input type="submit" value="Send" />
    </form>
  </body>
</html>

post.html


<html>
  <head>
    <meta charset="utf-8" />
    <title>Flask Sample</title>
  </head>
  <body>
    <h1>Flask Smaple</h1>
message:{{message}}
  </body>
</html>

After implementation, run ʻapp.py` to launch the Flask application.

(flask_sample)$ python /sample/app.py
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

If you access http: // Virtual environment private IP: 5000 / with a browser after startup, ʻindex.htmlwill be displayed. If you can confirm it, the operation check ofFlaskis completed. Next, build an AP server withNGINX Unit`.

NGINX Unit

NGINX Unit is a lightweight application server developed by NGINX. You can run applications in multiple languages, so you can run applications in different languages on the same server. The language supports Python, PHP, Go, Perl, Ruby, Node.js, Java. In addition, different versions in the language can co-exist and run. (Python2.7 and Python3, etc.) You can change the settings in real time without stopping the server via API or JSON, so you can change the settings seamlessly without stopping the service.

Installation

The Official Document has the installation method for each OS.

Get out of the venv virtual environment and add a yum repository.

(flask_sample)$ deactivate
$ sudo vi /etc/yum.repos.d/unit.repo
[unit]
name=unit repo
baseurl=https://packages.nginx.org/unit/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

Install it.

$ sudo yum install -y unit
$ sudo yum install -y unit-devel unit-go unit-jsc8 unit-perl unit-php unit-python

Sets the automatic startup of the NGINX Unit.

$ sudo systemctl enable unit
Created symlink from /etc/systemd/system/multi-user.target.wants/unit.service to /usr/lib/systemd/system/unit.service.
$ sudo service unit start
Redirecting to /bin/systemctl start unit.service
$ sudo service unit status
Redirecting to /bin/systemctl status unit.service
● unit.service - NGINX Unit
   Loaded: loaded (/usr/lib/systemd/system/unit.service; enabled; vendor preset: disabled)
   Active: active (running)since fire 2019-11-05 15:42:47 UTC; 7h ago
 Main PID: 5714 (unitd)
   CGroup: /system.slice/unit.service
           ├─5714 unit: main v1.12.0 [/usr/sbin/unitd --log /var/log/unit/unit.log --pid /var/run/unit/unit.pid --no-daemon]
           ├─5716 unit: controller
           └─5717 unit: router

You can confirm that NGINX Unit can be started by service unit status.

Make settings for Flask

Set the NGINX Unit to run Flask applications. Set the configuration file to GET from the NGINX Unit socket and load the Flask application into NGINX Unit. Unix sockets for controlling the NGINX Unit are located in /var/run/unit/control.sock. (The location depends on the OS)

$ cd /sample
$ sudo curl --unix-socket /var/run/unit/control.sock http://localhost/config/ > config.json
$ vi config.json
{
  "listeners": {
    "*:8080": {
      "pass": "applications/flask_app"
    }
  },

  "applications": {
    "flask_app": {
      "type": "python",
      "processes": 2,
      "path": "/sample/",
      "module": "app"
    }
  }
}

--listers: Set the port. The value of pass in *: 8080 is linked to the hierarchy of ʻapplications`.

PUT the created configuration file to the socket of NGINX Unit to reflect the configuration.

$ sudo curl -X PUT --data-binary @config.json --unix-socket /var/run/unit/control.sock http://localhost/config
{
	"success": "Reconfiguration done."
}

When success returns, the setting is complete. You can also check the settings.

$ sudo curl --unix-socket /var/run/unit/control.sock http://localhost/
{
	"certificates": {},
	"config": {
		"listeners": {
			"*:8080": {
				"pass": "applications/flask_app"
			}
		},

		"applications": {
			"flask_app": {
				"type": "python",
        "processes": 2,
				"path": "/sample/",
				"module": "app"
			}
		}
	}
}

Start the virtual environment and access http: // localhost: 8080 /.

$ source venv/bin/activate
(flask_sample)$ curl http://localhost:8080/
<html>
  <head>
    <meta charset="utf-8" />
    <title>Flask Sample</title>
  </head>
  <body>
    <h1>Flask Smaple</h1>
    <form action="sample" method="post">
      <input type="text" name="message" />
      <input type="submit" value="Send" />
    </form>
  </body>
</html>

Construction is complete when ʻindex.html is displayed. Even if you access it with a browser, ʻindex.html is displayed. That's all for building the NGINX Unit. Next, build the web server NGINX.

NGINX

It is an open source web server that is lightweight and fast, and is attracting attention as a potential alternative to Apache. Compared to Apache, it is superior in terms of scalability, and features such as processing performance, parallel processing, and low memory usage. This time it will be used as a proxy server.

Install NGINX on CentOS

NGINX officially publishes a yum repository, so install from that repository. Add the repository and install by referring to the description on Official page.

Add repository

Once out of the Python virtual environment. Add the yum repository. Add /etc/yum.repos.d/NGINX.repo.

$ sudo vi /etc/yum.repos.d/NGINX.repo
[NGINX]
name=NGINX repo
baseurl=http://NGINX.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1

Installation

Check the repository.

$ sudo yum info nginx
Available Packages
Name        : NGINX
Arch        : x86_64
Epoch       : 1
Version     : 1.16.1
Release     : 1.el7_4.ngx
Size        : 754 k
Repo        : NGINX/x86_64
Summary     : High performance web server
URL         : http://NGINX.org/
License     : 2-clause BSD-like license
Description : NGINX [engine x] is an HTTP and reverse proxy server, as well as
            : a mail proxy server.

If you can confirm that NGINX exists in the repository with the yum info command, install it.

$ sudo yum install nginx

Set automatic startup, Start NGINX.

$ sudo systemctl enable nginx
$ sudo service start nginx
$ ![nginx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239179/0d818e0a-7aee-8a07-af95-72d34dfaa824.png)
service status nginx
● NGINX.service - NGINX - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/NGINX.service; enabled; vendor preset: disabled)
   Active: active (running)

After launching NGINX, access the http: // private IP of the virtual environment in your browser. If the following screen is displayed, the startup is complete.

nginx.png

Cooperation between NGINX and NGINX Unit

NGINX configuration file

NGINX operates as a WEB server or proxy server in front of NGINX Unit. Proxy the request to the application to the Nginx Unit. The NGINX configuration file is located in /etc/nginx/conf.d.

$ sudo vi /etc/nginx/conf.d/app.conf
upstream unit-python {
        server 127.0.0.1:8080;
}
server {
    listen 80;
    server_name localhost;

    location ~ / {
      proxy_pass http://unit-python;
      proxy_set_header Host $host;
    }
}

Restart NGINX and go to http: // localhost /.

$ sudo service restart nginx
$ curl http://localhost/
<html>
  <head>
    <meta charset="utf-8" />
    <title>Flask Sample</title>
  </head>
  <body>
    <h1>Flask Smaple</h1>
    <form action="sample" method="post">
      <input type="text" name="message" />
      <input type="submit" value="Send" />
    </form>
  </body>
</html>

If'index.html'is displayed, proxy settings are complete. You can access http: // private IP of the virtual environment with a browser and check ʻindex.html`. This completes the construction of the Python web application environment.

Summary

We built the environment of the WEB application with NGINX + NGINX Unit + Flask. Since NGINX Unit specializes in the operation of microservices, I think it will continue to attract attention in the future. I would like to continue to touch on it.

Recommended Posts

Run Python web apps on NGINX + NGINX Unit + Flask
Run python wsgi server on NGINX Unit
Run Flask on CentOS with python3.4, Gunicorn + Nginx.
[Python] Run Flask on Google App Engine
Vienna with Python + Flask web app on Jenkins
Run Openpose on Python (Windows)
Run Tensorflow 2.x on Python 3.7
Run Python CGI on CORESERVER
Run unix command on python
Web application with Python + Flask ② ③
Web application with Python + Flask ④
Sample to put Python Flask web app on Azure App Service (Web App)
Preparing to run Flask on EC2
Monitor Python web apps with Prometheus
Run Python on Schedule on AWS Lambda
Run TensorFlow Docker Image on Python3
Periodically run Python on Heroku Scheduler
Run different versions of Python (wsgi) apps on one development environment
Create a Python3.4 + Nginx + uWSGI + Flask Web application execution environment with haste using pyenv on Ubuntu 12.04
Run servo with Python on ESP32 (Windows)
Getting Started with Flask with Azure Web Apps
Run AzureKinect in Python on Christmas Eve.
Download files on the web with Python
Run servomotor on Raspberry Pi 3 using python
Easy web app with Python + Flask + Heroku
[Python] Run Headless Chrome on AWS Lambda
Run Python code on A2019 Community Edition
Run a Python web application with Docker
Run Python in C ++ on Visual Studio 2017
Install Python3 and Django on Amazon Linux (EC2) and run your web server
Create a web application execution environment of Python3.4 + Nginx + uWSGI + Flask with haste using venv on Ubuntu 14.04 LTS
[Raspberry Pi] Publish a web application on https using Apache + WSGI + Python Flask
The key to deploying Flask apps using Python Buildpack on Cloud Foundry (Diego)
Until you install Python with pythonbrew and run Flask on a WSGI server
Periodically run a python program on AWS Lambda
Install and run Python3.5 + NumPy + SciPy on Windows 10
Put MicroPython on Windows to run ESP32 on Python
Python web framework Django vs Pyramid vs Flask December 2015
Run Python YOLOv3 in C ++ on Visual Studio 2017
How to run MeCab on Ubuntu 18.04 LTS Python
Hello World with nginx + uwsgi + python on EC2
Deploy Django apps on Ubuntu + Nginx + MySQL (Build)
Run Zookeeper x python (kazoo) on Mac OS X
Monitor Python apps with New Relic's APM (Flask)
Launch a web server with Python and Flask
A memorandum for touching python Flask on heroku
Run pip install on MacOS Python 3.7 or later
Build Python3 + flask environment on GCP Compute Engine
(For myself) AWS_Flask_3 (Install / Run Flask on AWS)
TensorFlow: Run data learned in Python on Android
Run Python on Apache to view InfluxDB data
Python on Windows
twitter on python3
Notes on Flask
python on mac
Python on Windbg
Python unit tests
Run the flask app on Cloud9 and Apache Httpd
Output log to console with Flask + Nginx on Docker
Parse and visualize JSON (Web application ⑤ with Python + Flask)
Launch a Python web application with Nginx + Gunicorn with Docker