This article is the fifth in the series of “Shang Yun Serial”. It will introduce how to deploy Flask application on Tencent Cloud CVM using programming website as an example. Specifically, how to deploy a Flask application in Debian 8 using uWSGI and Nginx, where Nginx acts as a front-end reverse proxy.
I listed here is the deployment of programming school site roughly operating steps, only for your reference.
The preparatory work
Before you start, you should have created an instance of Tencent Cloud CVM (Debian 8 OS), or any other cloud server, and configured a non-root user as described in Cloud Serial 2 above. The user should have sudo permission.
Get the application code base
The first thing you should have is a Flask app that works. Of course, you can also use the codebase of the programist website to demonstrate.
I deployed the application code in the /var/www/ directory. Enter the following command to create the directory:
You can clone the app codebase directly from Github:
cd /var/www
git clone https://github.com/bingjin/codingpy.git
Copy the code
You can also obtain it from the Git server set up in Cloud Serial 3.
To avoid having to log in to the server and manually pull each time, we set up post-receive hooks in the central code base. Every time a new update is pushed locally to the server, the code in the target code base is automatically updated.
There is no need to set up a Git server without multi-party cooperation.
Create a working directory under /var/www/ :
cd /var/www && mkdir codingpy
Copy the code
Then go to the hooks directory in the codingpy.git directory and create the post-receive file:
sudo su - git
cd repositories/codingpy.git/hooks/
vim post-receive
Copy the code
I use the plan provided by https://gist.github.com/thomasfr/9691385, you can also according to the actual situation of the application.
After saving the post-receive file, run the following command:
After that, the files in the /var/www/codingpy/ directory will be automatically updated every time an update is pushed locally.
Installing required Components
The Flask application uses Python 3, Nignx as a reverse proxy server, and Redis for caching. We use the apt-get command to install:
sudo apt-get install python3-pip python3-dev nginx redis
Copy the code
Python3-pip installs the PIP package manager, which is used to manage the dependency packages for Flask applications. Python 3 is automatically installed when python3-PIP is installed. Python3-dev will be used to build uWSGI packages.
If your application is based on Python 2, do:
sudo apt-get install python-pip python-dev nginx redis
Copy the code
Creating a Virtual Environment
If you’re only deploying a Python/Flask application on a production server, it doesn’t matter if you don’t use a virtual environment. However, it is best practice to separate the web application environment from the system environment. Considering that other applications can be deployed on the CVM, it is recommended to create a separate virtual environment using virtualEnv for deployment.
Virtualenv Package description: Virtualenv
First, install the Virtualenv package using PIp3.
cd /var/www
virtualenv -p /usr/bin/python3 venv
source venv/bin/activate
Copy the code
The -p option specifies the Python version in the virtual environment.
Virtualenv works with Python 2 and 3. With Python 3, you can also use the built-in Pyvenv package to quickly create a virtual environment without having to install virtualEnv.
Installing application dependencies
The last step in the previous section activates the new virtual environment. We go to the project files directory and install all of the application’s dependencies through the requirements.txt file.
(venv) cd codingpy
(venv) pip install -r requirements.txt
Copy the code
The Pillow, Psycopg2, gEvent, and other libraries may report errors during installation because the Debian system still lacks the components needed to build these packages. You can follow the error message to install the appropriate resource pack.
Sudo apt-get install libjpeg8-dev postgrseql-server-dev-9.4Copy the code
If other errors occur, you are advised to use search engines to find solutions.
Test uWSGI
After installing the dependency packages, we also need to create a file in the project directory as the entry point for the application, since we intend to deploy the Flask application through uWSGI. This file tells the uWSGI server how to interact with the application.
We’ll call this file wsgi.py:
(venv) $ vim /var/www/codingpy/wsgi.py
Copy the code
Here’s the simplest example:
from manage import app
if __name__ == "__main__":
app.run()
Copy the code
Next, test whether the uWSGI server is running properly by running the following command:
(venv) $uWSgi --socket 0.0.0.0:5000 --protocol= HTTP -w WSgi :appCopy the code
Open a browser, enter the IP address of the server, and specify the access port 5000:
http://server_domain_or_IP:5000
Copy the code
You should be able to see the application’s interface.
Configuration uWSGI
We’ve just tested that uWSGI can run our Flask application properly, but not in a way that is suitable for long-term use. You can create a uWSGI configuration file specifying the desired run options.
Put this file in the root directory of your project and name it codingpy.ini.
vim /var/www/codingpy/codingpy.ini
Copy the code
The first line of the file should be [UWSGi] so that UWSGI will apply the configuration in the file. Specify the module name wsgi.py, omit the suffix, and specify the name of the callable object in the module as app:
[uwsgi]
module = wsgi:app
Copy the code
Then, let uWSGI start in master mode and generate five worker processes to handle the request; I also turned on gEvent mode and set the number of threads and other options:
master = true
processes = 5
threads = 100
gevent = 100
async = 100
Copy the code
When testing uWSGI, we exposed the application to port 5000. However, we intend to use Nginx to handle the actual client requests, which Nginx then passes to uWSGI. Since both Nginx and uWSGI run on the same machine, it is better to use Unix sockets because they are more secure and faster. We named the socket codingpy.sock and placed the file in the /var/tmp/ directory.
Also, modify the permissions on the socket. Since we will later grant ownership of the uWSGI process to the Nginx user group, make sure that the user group to which the socket belongs can read and write it. Added the vaccum option to clear the socket when the process terminates.
socket = /tmp/codingpy.sock
chmod-socket = 660
vacuum = true
Copy the code
Next, you also set the die-on-term option. The init system and uWSGI interpret the process signal SIGNTERM differently and perform different operations. This ensures that both perform the same behavior.
In practice, my Flask application was not getting the environment variables correctly, so I chose to pass them in through the uWSGI configuration. I placed all the environment variables in the.envs file in the root directory and imported them at uWSGI startup with the following Settings:
for-readline = .envs
env = %(_)
endfor =
Copy the code
After configuring the options, save the file and exit.
Create the Systemd Unit file
In Debian 8 and Ubuntu 16.04, Systemd has become the default init system. We will create a Systemd Unit file that will automatically start uWSGI and Flask applications when the server starts.
Create a.service file in /etc/systemd/system:
sudo vim /etc/systemd/system/codingpy.service
Copy the code
First, configure the [Unit] section to specify metadata and dependencies. We set the description of the service to tell the init system to wait until network conditions are met before starting the service.
[Unit]
Description=uWSGI instance to serve codingpy.com
After=network.target
Copy the code
Then, configure the [Service] section to specify the user and user group to which the process belongs. Since earlgrey, the daily user we created, owns the related files, we set him to the process owner. In addition, set the owning user group to www-data so that Nginx can communicate with uWSGI processes.
Next, complete the working directory mapping, set up environment variables, and tell the init system the path to the executable file for the uWSGI process. Then specify the command to start the service. Systemd requires that the full path to the uWSGI executable be specified.
[Service]
User=earlgrey
Group=www-data
WorkingDirectory=/home/earlgrey/codingpy
Environment="PATH=/var/www/venv/bin"
ExecStart=/var/www/venv/bin/uwsgi --ini codingpy.ini
Copy the code
Finally, add the [Install] section. This tells Systemd which service to link to when it starts. We want to start the service when the multi-user system is up and running:
[Install]
WantedBy=multi-user.target
Copy the code
Save and close the file. We can now start the created service and set it to run on server startup:
sudo systemctl start codingpy
sudo systemctl enable codingpy
Copy the code
Configure Nginx
After completing the configuration in the previous section, the uWSGI server should be up and running, waiting to process requests on the specified socket. Now we need to configure Nginx to forward network requests to this socket using the UWSGi protocol.
First, create a new server module configuration file in the Site-available directory of Nginx. Call it Codingpy, in keeping with the name elsewhere:
sudo vim /etc/nginx/sites-available/codingpy
Copy the code
Enter the following configuration to have Nignx listen on the default port 80 and use this server block to handle requests for server domain names or IP addresses:
server { listen 80; server_name codingpy.com, http://www.codingpy.com; location / { include uwsgi_params; uwsgi_pass unix:/var/www/codingpy/codingpy.sock; }}Copy the code
The Location block matches all the requests that meet the requirements. Uswgi_params contains some of the required uWSGI parameters. The request is then forwarded to the defined socket using the UWSGI_pass directive.
That’s the setup for Nginx. Save and close the file. To make the configuration work, link the above file to the site-enabled directory:
sudo ln -s /etc/nginx/sites-available/codingpy /etc/nginx/sites-enabled
Copy the code
Then run the following command to test the syntax of the file configuration:
If the output does not show that there is a problem, we can restart the Nginx process and read the new server configuration:
sudo systemctl restart nginx
Copy the code
Now you can open the server’s URL or domain name in your browser and check whether the Flask app responds to requests properly:
http://server_domain_or_IP
Copy the code
conclusion
In this article, we created a virtual environment for running Flask applications and configured the uWSGI server to interact with the Flask applications. We then created the Systemd service file to automatically run the application server when the server starts. We also configured Nginx to forward network requests to the application server.
You can follow the general steps in this article to deploy your own Flask application.
In the following articles, I will introduce how to access Tencent cloud services such as CDN for programming website.
(Photo from DigitalOcean)