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.
Use NGINX as the web server, NGINX Unit as the AP server, and Flask as the Python web framework.
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
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 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.
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.
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.
Install Flask in the venv virtual environment.
(flask_sample)$ pip install Flask
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.
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.
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.
NGINX officially publishes a yum repository, so install from that repository.
Add the repository and install by referring to the description on Official page.
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
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
$ 
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 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.
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