在 Ubuntu 16.04 下部署 Django

前言

本文所述全部内容在 Ubuntu 16.04.3 LTS 下测试通过,其他系统或版本可以评论进行讨论。

所使用到的软件如下

  • Nginx
  • Gunicorn
  • Python 3
  • systemd

温馨提示:使用本教程需要一个可以运行 sudo 命令的用户,但为了安全,真正的

全新安装

配置用户

通常情况下,个人用户所用服务器均是以 root 用户登录的,但如果网络服务运行在 root 用户下,则虽然方便却不安全,因此本文采用一个普通用户「singee」进行网络配置

1
2
3
useradd -m -s /bin/bash singee  #添加了一个用户名为 singee 的用户
usermod -a -G sudo singee #给予 singee 管理员权限
passwd singee #为 singee 设置密码

但是一般情况下的配置依然使用平常所使用的账户来进行,新建的 singee 用户仅用来传输文件和运行网络服务

升级软件仓库与所有软件

1
2
sudo apt-get update
sudo apt-get upgrade

如果有特殊需求,此步可跳过

安装 git 与 nginx

如果所使用的系统还未安装过 git 或 nginx,可以通过以下命令安装

1
2
3
sudo apt-get update
sudo apt-get install git
sudo apt-get install nginx

安装 Python 3

如果所使用的系统还未安装过 Python 3,可以通过以下命令安装

1
2
3
sudo apt-get update
sudo apt-get install python3 python3-pip
sudo pip3 install virtualenv

如果所使用的云主机配置了防火墙或安全组(或其他同类不同名服务),则需要先配置好放行一些端口

启动 Nginx 服务

1
sudo service nginx start

这时,在浏览器中直接输入服务器域名,如果能看到一个写着「Welcome to Nginx!」的页面就代表安装成功

准备部署

好了,现在开始就可以正式进行 Django 部署了

拷贝文件

本部分使用新建的 singee 用户进行

生成目录结构

1
2
3
cd /home/singee  #或直接使用 cd ~ 
mkdir -p sites/test
cd sites/test

建立完成后目录如下:

1
2
3
4
.
└── sites
└── test
└── test

其中的「sites」目录用于存放网站,第一层 test 包含两个文件夹:env 虚拟环境(稍后配置)与 test 网站主目录。

建议:将所有的 test 全都替换为你的 Django 的项目名称

配置虚拟环境

1
2
cd ~/sites/test
virtualenv --python=python3.6 env

注意这里需要显示的提供 --python=python3 来指定环境,因为 Ubuntu 系统默认已经安装了 Python 2,如果不显示指定则会默认使用 Python 2。

完成后目录结构如下

1
2
3
4
5
6
7
8
9
.
└── sites
└── test
├── env
│   ├── bin
│   ├── include
│   ├── lib
│   └── pip-selfcheck.json
└── test

上传文件

使用 SFTP 上传工具,将网站全部内容上传至 ~/sites/test/test 文件夹下,上传后目录结构类似如下

1
2
3
4
5
6
7
8
9
10
11
12
.
└── sites
└── test
├── env
│   ├── bin
│   ├── include
│   ├── lib
│   └── pip-selfcheck.json
└── test
   ├── ...
   ├── ...
   └── ...

项目配置

以下使用 singee 用户修改 test/settings.py 文件内容(也可本地修改完成后使用 singee 用户上传)

关闭 DEBUG 并设置域名白名单

1
2
DEBUG = False
ALLOWED_HOSTS = ['127.0.0.1', 'localhost ', '.singee.me']

其中,「ALLOWED_HOSTS」填写以 . 开头的域名代表允许子域名

Static 与 Media

按照类似下面的代码的方式进行设置

1
2
3
4
5
6
7
8
9
10
11
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'

if not DEBUG:
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
else:
STATICFILES_DIRS = (
"static/",
)

开始部署

以下使用 singee 用户运行

进入虚拟环境

1
2
3
cd ~/sites/test
source env/bin/activate
cd test

目前已经激活了虚拟环境并处于 ~/sites/test/test 目录下,这也是下面各个步骤的基础,如果在下面运行的过程中不慎中断,则需重新执行本部分命令来重新切换目录、设置环境

给予 manage.py 文件执行权限

1
chmod +x manage.py

注:此命令是后文 ./manage.py 的基础,同时需要保证 manage.py 文件第一行为 #!/usr/bin/env python,否则需要加上或使用 python manage.py 来代替 ./manage.py 命令

安装依赖

1
2
pip install gunicorn
pip install -r requirements.txt

收集静态文件

1
./manage.py collectstatic

迁移数据库文件

1
./manage.py migrate

数据库的迁移可能并没有这么简单,此处只以最简单的迁移为例,具体请参考 Django 开发文档

配置 Nginx

先在服务器的 /etc/nginx/sites-available/ 目录下新建一个配置文件,文件名一般设置为域名,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
charset utf-8;
listen 80;
server_name test.singee.site;

location /static {
alias /home/singee/sites/test/test/static;
}
location /uploads {
alias /home/singee/sites/test/test/media;
}

location / {
proxy_set_header Host $host;
proxy_pass http://unix:/tmp/test.singee.site.socket;
}
}

如果需要开启 HTTPS 支持,则添加如下内容

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
server {
charset utf-8;
listen 80;
server_name test.singee.site;

location /static {
alias /home/singee/sites/test/test/static;
}
location /uploads {
alias /home/singee/sites/test/test/media;
}

rewrite ^(.*) https://$host$1 permanent;
}

server {
charset utf-8;
listen 443 ssl http2;
server_name test.singee.site;

location /static {
alias /home/singee/sites/test/test/static;
}

location /uploads {
alias /home/singee/sites/test/test/media;
}

location / {
proxy_set_header Host $host;
proxy_pass http://unix:/tmp/test.singee.site.socket;
}

ssl on;
ssl_certificate /etc/nginx/sites-available/test.singee.site.crt;
ssl_certificate_key /etc/nginx/sites-available/test.singee.site.key;

# HSTS Preload(可选)
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

}

然后将文件链接到 /etc/nginx/sites-enabled/ 目录中,代码如下

1
sudo ln -s /etc/nginx/sites-available/test.singee.site /etc/nginx/sites-enabled/test.singee.site

最后删除掉 /etc/nginx/sites-enabled/ 目录中的 default 文件

配置 Gunicorn

此部分所有命令需要在 root 用户权限下使用

/etc/systemd/system/ 目录下新建一个文件扩展名为 .service 的文件,例如 gunicorn-test.service,将此文件的内容设置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
Description=Gunicorn instance to serve test # 这里可以随意书写
After=network.target

[Service]
User=singee # 这里修改为用户名
Group=www-data
WorkingDirectory=/home/singee/sites/test/test #需要修改
Environment="PATH=/home/singee/sites/test/env" #需要修改
ExecStart=/home/singee/sites/test/env/bin/gunicorn --workers 5 --bind unix:/tmp/test.singee.site.socket test.wsgi:application #需要修改*

[Install]
WantedBy=multi-user.target

*:此部分内容要注意两点,一是 unix:/tmp/test.singee.site.socket 要与之前 Nginx 设置中 proxy_pass http:// 后的内容保持一致,一是 test.wsgi 中的 test 要与 Django 中的 Project 名称相同

然后通过以下命令即可让其开机启动

1
2
sudo systemctl start gunicorn-test
sudo systemctl enable gunicorn-test

配置定时任务

以下命令需要以 root 用户运行

最后,如果有需要执行定时任务的脚本,则需要设定定时任务

在 bash 中输入 crontab -e 后打开定时任务配置页,按照 Ubuntu 定时任务的格式设置即可,不过这里需要注意两点——一是第一步必须先切换到网站目录(第二个 test)文件夹下,二是调用 Python 时必须使用 env 下的全路径。示例如下

1
3    *    *     *    cd /home/singee/sites/test/test && /home/singee/sites/test/env/bin/python /home/singee/sites/test/test/manage.py autodo