Detailed tutorial on deploying a web app under the Python framework
This article describes how to deploy a web app in Python. The sample code is based on Python 2.x. For more information, see
As a qualified developer, it is far from enough to complete development in a local environment. We need to deploy the Web App on a remote server so that the majority of users can access the website.
Many developers regard deployment as the work of O & M personnel. This is totally wrong. First, the DevOps concept has recently become popular, that is, development and O & M must become a whole. Second, the difficulty of O & M is actually closely related to the development quality. The code is spam, and O & M cannot work anymore. Finally, the DevOps concept needs to integrate O & M, monitoring, and other functions into development. Do you want to avoid service interruption during server upgrade? This must be taken into account during development.
Next, we will deploy awesome-python-webapp to the Linux server.
Build a Linux Server
To deploy it on Linux, you must first have a Linux server. If you want to experience it on the Internet, you can apply for an EC2 Virtual Machine (free for 1 year) on Amazon AWS or use some cloud servers in China. Generally, Ubuntu Server images are provided. If you want to deploy it locally, install the Virtual Machine. VirtualBox is recommended.
The Linux Server we selected is Ubuntu Server 12.04 LTS, because apt is too simple. If you are going to use another Linux version, there is no problem.
After installing Linux, make sure that the ssh service is running. Otherwise, you must install it through apt:
?
1 |
$ Sudo apt-get install openssh-server |
With the ssh service, you can locally connect to the server. We recommend that you copy the public key to. ssh/authorized_keys of the server user. In this way, you can achieve password-free connection through the certificate.
Deployment Method
During local development, we can use the WSGI server that comes with Python. However, on the server, we obviously cannot use the built-in development edition server. There are many WSGI servers that can be selected. We choose gunicorn: it uses a Master-Worker mode similar to Nginx, and supports gevent. You can achieve extremely high performance without modifying the code.
In addition, we also need a high-performance Web server, which can process static resources and send dynamic requests to gunicorn as a reverse proxy. Gunicorn is responsible for calling our Python code. This model is as follows:
Nginx is responsible for distributing requests:
On the server side, we need to define the directory structure for deployment:
Copy the Code as follows:
/
+-Srv/
+-Awesome/<-- Web App root directory
+-Www/<-- stores Python source code
| +-Static/<-- stores static resource files
+-Log/<-- stores logs.
To deploy a new version on a server, consider what to do when the new version is not running normally and needs to be rolled back to the old version. It is impossible to overwrite the old file with new code each time. A version control mechanism is required. Since the Linux system provides the soft link function, we use www as a soft link, which directory it directs to and which directory is the current running version:
The Nginx and gunicorn configuration files only need to point to the www directory.
Nginx can be directly started as a service process, but gunicorn does not work yet. Therefore, Supervisor debut! The Supervisor is a tool used to manage processes. It can start services as the system starts. It also monitors service processes at all times. If a service process unexpectedly exits, the Supervisor can automatically restart the service.
To sum up, we need to use the following services:
Nginx: high-performance Web SERVER + reverse proxy;
Gunicorn: High-Performance WSGI server;
Gevent: converts the Python synchronization code to the library of the asynchronous coroutine;
Supervisor: a tool used to monitor service processes;
MySQL: database service.
You can directly install the above services on a Linux server using apt:
?
1 |
$ Sudo apt-get install nginx gunicorn python-gevent supervisor mysql-server |
Then, install the Python library used by our Web App:
?
1 |
$ Sudo apt-get install python-jinja2 python-mysql.connector |
Create a directory/srv/awesome/and a subdirectory on the server.
Initialize the MySQL database on the server and copy the database Initialization Script schema. SQL to the server for execution:
?
1 |
$ Mysql-u root-p <schema. SQL |
The server is ready.
Deployment
Using FTP, SCP, or rsync to copy files? If you need manual replication, it is okay to use it once or twice. If you deploy it 50 times a day, it will be slow, inefficient, and prone to errors.
The correct deployment method is to use tools and scripts to automate the deployment. Fabric is an automated deployment tool. Fabric is developed in Python, so the deployment script is also written in Python, which is very convenient!
To deploy Fabric, you must install Fabric on the local machine (Development machine, not Linux Server:
?
Fabric does not need to be installed on Linux servers. Fabric directly logs on to the server using SSH and runs the deployment command.
The next step is to write the deployment script. The deployment script of Fabric is fabfile. py. We put it in the directory of awesome-python-webapp, which is similar to the www directory:
Copy the Code as follows:
Awesome-python-webapp/
+-Fabfile. py
+-Www/
+ -...
The Fabric script is easy to write. First, import the Fabric API and set the deployment variables:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Fabfile. py Import OS, re From datetime import datetime # Import Fabric API: From fabric. api import * # Server login Username: Env. user = 'Michael' # The sudo user is root: Env. sudo_user = 'root' # Server address. Multiple server addresses can be deployed in sequence: Env. hosts = ['192. 168.0.3 '] # Server MySQL user name and password: Db_user = 'www-data' Db_password = 'www-data' |
Then, each Python function is a task. First, we compile a packaging task:
?
1 2 3 4 5 6 7 8 9 10 11 |
_ TAR_FILE = 'dist-awesome.tar.gz' Def build (): Primary des = ['static ', 'templates', 'transwarp', 'favicon. ico ',' *. py'] Excludes = ['test', '. *', '*. pyc',' *. pyo'] Local ('rm-f dist/% s' % _ TAR_FILE) With LCD (OS. path. join (OS. path. abspath ('.'), 'www ')): Cmd = ['tar ',' -- dereference ','-czvf ',' ../dist/% s' % _ TAR_FILE] Cmd. extend (['-- exclude = \' % s \ ''% ex for ex in excludes]) Cmd. extend (DES) Local (''. join (cmd )) |
Fabric provides local ('... ') to run local commands. with LCD (path) can set the directory of the current command to the directory specified by LCD (). Note that Fabric can only run command line commands, in Windows, the Cgywin environment may be required.
Run the following command in the awesome-python-webapp directory:
?
See the dist-awesome.tar.gz file created in the distdirectory.
After packaging, we can continue to write the deploy task, upload the package file to the server, decompress the package, reset the www soft link, and restart related services:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
_ REMOTE_TMP_TAR = '/tmp/% s' % _ TAR_FILE _ REMOTE_BASE_DIR = '/srv/awesome' Def deploy (): Newdir = 'www-% s' % datetime. now (). strftime ('% y-% m-% d _ % H. % M. % s ') # Delete an existing tar file: Run ('rm-f % s' % _ REMOTE_TMP_TAR) # Upload a new tar file: Put ('dist/% s' % _ TAR_FILE, _ REMOTE_TMP_TAR) # Create a new directory: With cd (_ REMOTE_BASE_DIR ): Sudo ('mkdir % s' % newdir) # Decompress the package to the new directory: With cd ('% s/% s' % (_ REMOTE_BASE_DIR, newdir )): Sudo ('tar-xzvf % s' % _ REMOTE_TMP_TAR) # Resetting soft links: With cd (_ REMOTE_BASE_DIR ): Sudo ('rm-f www ') Sudo ('ln-s % s www '% newdir) Sudo ('chown www-data: www-data www ') Sudo ('chown-R www-data: www-data % s' % newdir) # Restart the Python service and nginx Server: With settings (warn_only = True ): Sudo ('supervisorctl stop awesome ') Sudo ('supervisorctl start awesome ') Sudo ('/etc/init. d/nginx reload ') |
Note that the run () function execution command is run on the server. with cd (path) is similar to with LCD (path). Set the current directory to cd () on the server () the specified directory. If a command requires the sudo permission, it cannot be run (), but sudo () is used for execution.
Configure a Supervisor
The above command for the Supervisor to restart gunicorn will fail, because we have not configured the Supervisor yet.
Compile a configuration file awesome. conf for the Supervisor and store it in the/etc/supervisor/conf. d/directory:
Copy the Code as follows:
[Program: awesome]
Command =/usr/bin/gunicorn -- bind 127.0.0.1: 9000 -- workers 1 -- worker-class gevent wsgiapp: application
Directory =/srv/awesome/www
User = www-data
Startsecs = 3
Redirect_stderr = true
Stdout_logfile_maxbytes = 50 MB
Stdout_logfile_backups = 10
Stdout_logfile =/srv/awesome/log/app. log
The configuration file uses [program: awesome] to specify the service name awesome, command to specify the command line for starting gunicorn, set the Start port of gunicorn to 9000, and WSGI processing function entry to wsgiapp: application.
After restarting the Supervisor, you can start and stop the services managed by the Supervisor at any time:
?
1 2 3 4 |
$ Sudo supervisorctl reload $ Sudo supervisorctl start awesome $ Sudo supervisorctl status Awesome RUNNING pid 1401, uptime 5:01:34 |
Configure Nginx
The Supervisor is only responsible for running gunicorn. We also need to configure Nginx. Put the configuration file awesome in the/etc/nginx/sites-available/directory:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Server { Listen 80; # Listening to port 80 Root/srv/awesome/www; Access_log/srv/awesome/log/access_log; Error_log/srv/awesome/log/error_log; # Server_name awesome.liaoxuefeng.com; # configure the Domain Name # Process static files/favicon. ico: Location/favicon. ico { Root/srv/awesome/www; } # Processing static resources: Location ~ ^ \/Static \/. * $ { Root/srv/awesome/www; } # Dynamic Request forwarding to port 9000 (gunicorn ): Location /{ Proxy_pass http: // 127.0.0.1: 9000; Proxy_set_header X-Real-IP $ remote_addr; Proxy_set_header Host $ host; Proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for; } } |
Then, create a soft link in the/etc/nginx/sites-enabled/directory:
?
1 2 3 |
$ Pwd /Etc/nginx/sites-enabled $ Sudo ln-s/etc/nginx/sites-available/awesome. |
Let Nginx reload the configuration file, without accident, our awesome-python-webapp should be running properly:
?
1 |
$ Sudo/etc/init. d/nginx reload |
If there are any errors, you can search for Nginx and App logs in/srv/awesome/log. If an error is reported when the Supervisor starts, you can view the log of the supervisor under/var/log/Supervisor.
If everything goes well, you can access awesome-python-webapp on the Linux server in your browser:
If the code is updated in the development environment, run the following command on the command line:
?
1 2 |
$ Fab build $ Fab deploy |
Automatic deployment completed! Refresh the browser to see the updated server code.
Note <>: For more exciting tutorials, please pay attention to the help house programming