It’s time to let everyone see what you write with the django blog (containing deployment tutorial video)

Author: HelloGitHub- Dream figure

Sample code relates to text, it has been updated to synchronize HelloGitHub-Team warehouse

Basic functions of blog has been developed almost, although there are many places you can improve, but we still hope for an early blog to deploy to the server, so that others can access via the Internet. As for the perfect place to be, you can wait a little bit after the deployment and iterative improvement. Now let us put on the blog server to deploy it!

↓↓↓ ↓↓↓ video here

Author personally recorded real machine deployment environment demonstrates the whole process, do not succeed you hit me!

B station demo (Ali cloud CentOS 7 systems) to watch the address: https: //

Note: Each step of this article are correct validation in a real environment. Unless you know what you are doing, it is recommended that every step tutorials are in strict accordance to, so you can ensure the successful completion of the deployment.

Pre-deployment preparation

We will use the more popular way Nginx + Gunicorn will django development blog to deploy their own servers, so that others can access your blog through the domain name. As for Nginx, Gunicorn what is being put aside, after reading this tutorial you will know their role and use of.

In order to deploy our blog, need to meet the following two conditions:

    The best have a server that can be accessed via the external network (if not, you can build a virtual machine on your computer, accessed via a virtual ip).

    Best to have a domain name (if not, you can only use the ip access, and can not be turned on HTTPS).

Server Configuration

This tutorial uses the local environment is Windows 10, server environment for CentOS 7 (64-bit). If your environment and I differ (such as Ubuntu) lead to some commands can not be executed, these commands are converted into command can be executed in your environment, with emphasis on understanding the role of each step, so that no matter what environment you are successfully complete the deployment, rather than mechanically copy and paste commands.

### log in to remote server

Server is usually located in the cloud, it requires the use of remote login tool to the server after you log in. I am using Xshell, Baidu Xshell download can be installed under Windows, software for schools and individual users is free.

How to remotely log on to the server not go into here, I believe you refer to some online tutorials is certainly able to log in successfully. If you’re like me, then use Xshell, there is a very detailed tutorial can refer to: teach you how to use a remote connection xshell linux server.

Creating a superuser

Successfully connect to a remote server, if it is a brand new server, usually we are the root user login. Deploy code is not enough security at root, the best is to build a new user (if you are already logged in, then a non-root user can skip this step). The following command creates a series of new user with root authority (the yangxg replace user name you want, I’m here to take my name Pinyin yangxg):

# 在 root 用户下运行这条命令创建一个新用户,yangxg 是用户名
# 因为我叫杨学光,所以我取的用户名是 yangxg
# 选择一个你喜欢的用户名,不一定非得和我的相同
[email protected]:~# adduser yangxg

# 为新用户设置密码
# 注意在输密码的时候不会有字符显示,不要以为键盘坏了,正常输入即可
[email protected]:~# passwd yangxg

# 把新创建的用户加入超级权限组
[email protected]:~# usermod -aG wheel yangxg

# 切换到创建的新用户
[email protected]:~# su - yangxg

# 切换成功,@符号前面已经是新用户名而不是 root 了
[email protected]:$

New users to create and change a success. If you are a new server, it is best to update the system, avoid the version is too old to bring trouble to install the software later. Run the following two commands:

[email protected]:$ sudo yum update
[email protected]:$ sudo yum upgrade

Update SQLite3

For convenience, we use the blog SQLite3 database, django 2.2 Requirements SQLite3 database version 3.8.3 or higher, and CentOS 7 system comes with django 2.2 version is below the minimum version required, so first of all to update SQLite3 version.


Chances are you’ll SQLite3 server system release has been higher than 3.8.3, you can skip this step. How to view SQLite3 version of it? Do sqlite3 –version

First, log on to the official Download sqlite to view the latest release version, up to the time to complete this tutorial, the latest version is 3.29.0, find the version of the source tarball, copy the download link, then downloaded to the server via wget command (I usually accustomed to source in ~ / src directory.)

# 创建 src 目录并进到这个目录
[email protected]:$ mkdir -p ~/src
[email protected]:$ cd ~/src

# 下载 sqlite3 源码并解压安装
[email protected]:$ wget
[email protected]:$ tar zxvf sqlite-autoconf-3290000.tar.gz
[email protected]:$ cd sqlite-autoconf-3290000
[email protected]:$ ./configure
[email protected]:$ make
[email protected]:$ sudo make install


If the command does not exist wget using sudo yum install -y wget installed.

So far SQLite3 update is completed, the next installation Python3.

Installation Python3 and Pipenv

CentOS 7 comes with Python 2.7 release, so you need to install Python3, for compatibility, we installed Python 3.6.4.

First, the installation may depend on:

[email protected]:$ sudo yum install -y openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel

Then download and unpack the Python source code 3.6.4:

[email protected]:$ cd ~/src
[email protected]:$ wget
[email protected]:$ tar -zxvf Python-3.6.4.tgz

Finally, compile and install:

[email protected]:$ cd Python-3.6.4
[email protected]:$ ./configure LD_RUN_PATH=/usr/local/lib LDFLAGS="-L/usr/local/lib" CPPFLAGS="-I/usr/local/include"
[email protected]:$ make LD_RUN_PATH=/usr/local/lib
[email protected]:$ sudo make install

Note that when installing Python, Python will depend SQLite3 library, so when configure through LD_RUN_PATH specified dependency search directory (since we updated before SQLite3 version, designated rely on search directory to ensure that the new SQLite3 dependencies), the other two a similar effect parameters.

Then enter python3.6 -V and pip3.6 -V command to test the results of the installation, output version installation was successful.

With pip, you can install the Pipenv:

[email protected]:$ sudo pip3.6 install pipenv


If the above command is given, probably because pip3.6 bin installed in the path of the current user (/ usr / local / bin /), using the command pip3.6 install pipenv –users Pipenv also mounted to the user at the current bin path on it.

Deploy code

Then we began to prepare to deploy code, let’s use the blog up and running in the service, which in the local development and the process is exactly the same. But in order to deploy applications to the server, we must first make the project a little configuration, open the, find ALLOWED_HOSTS, change it to:


ALLOWED_HOSTS = ['', 'localhost ', '']

After the specified value ALLOWED_HOSTS, django will only allow access to our application by specifying the domain name, such as this only allows, localhost and and any of its subdomains add a point (before allowing access to the domain represents the domain name sub-domain names under) access (ie the value of an HTTP packet header Host must be more than a specified domain name, usually you enter the domain name in the browser to access the site, the value will be set to Host site’s domain name), so you can avoid the HTTP Host header attack.

Django project there will be some CSS, JavaScript and other static files, in order to be able to easily make Nginx handle requests for these static files, we collect all the static files in a project into a unified directory, this directory is usually located in the root django projects directory, and named as static. To accomplish these tasks, you need to do some necessary configuration in the project configuration file:


# 其他配置...

STATIC_URL = '/static/'
# 加入下面的配置
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

STATIC_ROOT i.e. static files designated collection path, designated here base_dir (project root directory, the file defined at the beginning) static folder under.

The key now is to put up the code to the server, and here we use git. First install git:

[email protected]:$ sudo  yum install -y git

The code is uploaded to GitHub and other code hosting platform, so that we can easily pull the code to the server. Git and GitHub uses believe you are already familiar, and not repeat them here process. If you do not know how to use, then you can Baidu own tutorials. Note that the database files do not upload!

I usually like to use code in ~ / apps / directory, let’s set about the file structure of the server used to store application code and other related documents:

# 在用户目录下创建 apps 目录并进入
[email protected]:$ mkdir -p ~/apps
[email protected]:$ cd ~/apps

# 拉取博客代码
[email protected]:$ git clone

Then enter the root directory of the project, installation project dependencies:

[email protected]:$ cd ~/apps/HelloDjango-blog-tutorial

[email protected]:$ pipenv install --deploy --ignore-pipfile

–Deploy parameters specified herein, Pipenv will only installed under the specified Pipfile [Packages] dependent. Because we are now online environment for deployment, dependent only relevant development environment we do not need.

–ignore-pipfile will make Pipenv installation project dependencies from Pipfile.lock file. Pipfile.lock accurate information items recorded dependencies, dependency information is read from here dependent information can be secured from being inadvertently modified or destroyed that the runtime environment because the dependencies sake unexpected problems.

Pipenv will automatically help us to create a virtual environment, then the project will depend on the installation to a virtual environment.

Then create a database about:

[email protected]:$ pipenv run python migrate

Start the development server:

[email protected]:$ pipenv run python runserver

Here we start the development server specified ip and port the server is running, it will allow port 8000 through the public network ip visit our blog.

Access ip: 8000, we can see a successful visit (which is a public network ip ip your server).

Use Gunicorn

Django development server official document emphasizes the use runserver open only for development and testing is not recommended for production environments. So we use the popular Gunicorn to start the server can be used in online environments.

First into the project root directory, installation Gunicorn:

[email protected]:$ pipenv install gunicorn

Because we modify the server is installed gunicorn, code Pipfile files and Pipfile.lock files are updated, so do not forget to change synchronized to the local, specific practices can learn on their own, here’s a reference:

# 服务端提交代码
[email protected]:$ git add Pipfile Pipfile.lock
[email protected]:$ git commit -m "add gunicorn dependency"
[email protected]:$ git push

# 本地拉取代码
git pull

Server back online in the project root directory, execute the following command to start the service:

[email protected]:$ pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b

To explain the meaning of each parameter.

`-W 2 represents two worker for processing start request (a worker can be understood as a process), the number of worker typically set 2-4 times the number of CPU cores.

-k gthread specify each worker process requests way, according to our practices, designated as gthread asynchronous mode can obtain higher performance, so we use this model.

-b, the service is bound to port 8000, run by the public network ip and port 8000 to access the application.

Access ip: 8000 (ip ip your public network server), the application of a successful visit, but we see that pattern completely chaotic. Do not worry, this is not a bug! Previously we use comes django development server, it will automatically help us deal with static style files, but Gunicorn and will not help us to do so. Because static files Gunicorn not good at something, you should give it to a more professional service to do the application, such as Nginx.

Start Nginx server

Nginx (engine x) is a high-performance HTTP server and reverse proxy web server, it functions very much, here we mainly deal with static files and to request a non-static files Gunicorn reverse proxy to use it.

When we visit a blog post details page, the server receives a request for the following two kinds:

    Displaying the details of information that is usually stored in a database, so you need to call the database to get data.

    Pictures, css, js and other presence server static files in a folder under.

For the former request, the data need to use django blog articles retrieved from the database, Nginx can not handle, it will forward the request to django application running in Gunicorn service, let django to deal with. The latter request for static files, just go to the folder where the files still get, Nginx will act on behalf of, no longer bother django.

To get static files using django is very time consuming, but Nginx can efficiently handle, which is why we want to use Nginx.

First install Nginx:

[email protected]:$ sudo yum install epel-release -y
[email protected]:$ sudo yum install nginx -y

Run the following command to start Nginx services:

[email protected]:$ sudo systemctl start nginx

In the browser input ip (do not enter the port, the default is port 80, Nginx listening for requests on port 80 by default), see the welcome screen instructions Nginx Nginx launch a success.

Nginx configuration

Nginx configuration file located in /etc/nginx/nginx.conf, you can open this file and see the contents inside, here are some key configuration:

user nobody nobody;
http {
    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {

The first is the user configuration for users and groups (respectively the first and the second argument) specifies the Nginx process is running, in order to prevent possible permissions problem, we change the current system user (my username is yangxg , belongs to the group yangxg, remember to change the user and group servers running your own, remember to save the file after modify the contents of):

user yangxg yangxg;

Then there under http configure a server module, the module is used to configure a virtual server service, to make this virtual service listening on the specified port and domain name. You can configure multiple server, which would start multiple virtual services for monitoring different ports or the same port, but different domain name, so you can deploy multiple web applications on the same server.

The server configuration we will explain in detail below, let’s look at include the server, include the specified path will include it in the configuration file, it is easy to manage modular configuration, for example, we can configure different web applications into / etc under /nginx/conf.d/ directory, this directory nginx will put this all to the end of the file containing the contents .conf configuration nginx.conf to be, without all piled into nginx.conf configured in such a configuration file is very bloated.

We configure the blog application, it says, in order to manage modular, we will write the next /etc/nginx/conf.d/ configuration directory. First create a new configuration file in conf.d directory on the server, I call it HelloDjango-blog-tutorial.conf. Write the following configuration elements:

server {
    charset utf-8;
    listen 80;

    location /static {
        alias /home/yangxg/apps/HelloDjango-blog-tutorial/static;

    location / {
        proxy_set_header Host $host;

First, we configured a virtual service, encoding is utf-8, listening to port 80.

Domain Name Service for, so the request from this domain will be handled by this service.

All URL matching / static requests by Nginx processing, alias specifies the directory where static files, so Nginx can be found in this directory request file back to the client.

Other forwards the request to run in a native application processing port 8000, we will Gunicorn for handling requests forwarded by Nginx in this port start.

Restart nginx allows configuration to take effect:

[email protected]:$ sudo systemctl restart nginx

Close DEBUG mode, collect static files

Under development environment, django order to facilitate debugging, will file configuration options DEBUG is True, so if run error, debugging information at a glance, it is very convenient in the development, but will be deployed to the line with to a huge security risk, so we dEBUG option is set to False, off debug mode, local in the dEBUG as follows:


Online servers updated with the latest code, and then run the command to gather static configuration file to the directory before STATIC_ROOT:

[email protected]:$ pipenv run python collectstatic

Then use Gunicorn start the service.

[email protected]:$ pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b

Now, the configuration of domain names (change your own domain name in the Nginx configuration), you can see the blog successfully deployed!

Process management Gunicorn

Now Gunicorn we started manually, once we exit the shell, the server shut down, blog inaccessible. Even start Gunicorn in the background, then it could restart the server crashes they have to log in again to start the server, very troublesome. Supervisor to manage Gunicorn used for this process, so that when the server is restarted or Gunicorn process unexpectedly crashes, Supervisor will help us to automatically restart Gunicorn.

Press Ctrl + C to stop Gunicorn service process has just started.

First, install the Supervisor Note the use of the system comes with pip2, because as of this writing tutorial does not support Supervisor Python3, but this does not affect use.

[email protected]:$ pip install supervisor

For convenience, I usually set the following directory structure (located in ~ / etc directory) to manage files relating Supervisor:


├── supervisor
│   ├── conf.d
│   └── var
│       ├── log
└── supervisord.conf

Supervisord.conf which is Supervior configuration file that contains configuration of conf.d. Under var directory used to store some files change frequently, such as socket files, pid files, log files stored under the log.

First, let’s establish the above directory structure:

[email protected]:$ mkdir -p ~/etc/supervisor/conf.d
[email protected]:$ mkdir -p ~/etc/supervisor/var/log

Supervisor then enters the profile generation at ~ / etc directory:

[email protected]:$ cd ~/etc
[email protected]:$ echo_supervisord_conf > supervisord.conf

Modify supervisor.conf, let Supervisor process produced some of the files are generated to the directory above we create, rather than the default specified in its place.

First, find the [unix_http_server] section, the file settings to the following values:


Let socket file that is generated in the ~ / etc / supervisor / var / directory. Note supervisor is not supported – expands to the user’s home directory, so use an absolute path is specified.

Similar modifications [supervisord] logfile path and file pidfile at the plate, as well as user changed the system user, this supervisor will start the process of running the system user to avoid possible rights issue:


There [supervisorctl] section below:


[The include] section, the lower /home/yangxg/etc/supervisor/conf.d/ list of all content-containing .ini files ending to the configuration, the modular configuration facilitates this process management, and the previous configuration file Nginx approach is similar.

files = /home/yangxg/etc/supervisor/conf.d/*.ini

Then we went to our new conf.d configuration blog application:

command=pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b

Talk about the meaning of various configurations:

[Program: hellodjango-blog-tutorial] indicative of the operational process applications, called hellodjango-blog-tutorial.

  • command is the command to execute when the process started.

  • directory specify the directory where the command is executed.

  • autostart with Supervisor start automatically start the process.

  • When the restart process unexpectedly quit autorestart.

  • user processes running user, to prevent rights issues.

  • stdout_logfile, stderr_logfile log output file.

Start Supervisor

[email protected]:$ supervisord -c ~/etc/supervisord.conf

-c Specifies the configuration file for the Supervisr start.

Supervisorctl process into the Management Console:

[email protected]:$ supervisorctl -c ~/etc/supervisord.conf

Execute the update command to update the configuration file and starts the application.

Browser, enter the domain name, you can see that normal service has been started.

CDN load faster using Bootstrap and jQuery’s

Our project uses Bootstrap and jQuery, we have these two documents are loaded from a local. If the server performance is poor, then load it takes a long time to open the website speed becomes unbearable. We use the CDN to load faster. Specifically, an alternate loading label base.html several static files:



Modified native code, code synchronization line to the server, execute the following commands to restart hellodjango-blog-tutorial application process:

[email protected]:$ supervisorctl -c ~/etc/supervisord.conf restart hellodjango-blog-tutorial 

Speed ​​access such sites will greatly enhance!

to sum up

Many deployment steps and complicated, because each environment is different, and therefore is the most error-prone deployment steps, be sure to find out the role of each step, so that when they encounter problems in order to solve targeted, if just merely copy and paste commands, and not know what they are doing, then once the error will be helpless.

Deployment Process Automation

Throughout the deployment process, we run a dozen commands, manually enter the N characters. If the code is to be updated every time a remote connection to the server, then execute these commands will become very troublesome. The next tutorial we will introduce the use Fabric automate the entire deployment process. Written after the deployment script, just execute a command, you can easily automate the entire deployment.

“Explain open source projects Series” – to let people interested in open source projects are no longer afraid, let sponsors open source projects are no longer alone. Follow our articles, you’ll discover the fun of programming, the use of open source projects and found to be involved so simple. Welcome messages to contact us, join us, so that more people fall in love with open source, open source contribution ~

Leave a Reply