django的部署方式有很多种,目前比较常见的是Nginx+Gunicorn+Supervisor,但如果按照这种方案部署下来,会耗费很长时间,对于像我这种搭建django仅仅为个人使用的需求来说过于复杂和浪费时间。本文基于部署无安全性和高性能需求的个人django项目为目的,不使用Gunicorn和Nginx,说明下部署流程。环境基于CentOS 7宝塔面板django 2.2Python 3.7.1

更新 SQLite3

为了方便,我们博客使用了 SQLite3 数据库,django 2.2 要求 SQLite3 数据库版本在 3.8.3 以上,而 CentOS 7 系统自带版本低于 django 2.2 所要求的最低版本,所以首先来更新 SQLite3 的版本。

有可能你使用的服务器系统发行版 SQLite3 已经高于 3.8.3,这一步就可以跳过。如何查看 SQLite3 的版本呢?请执行sqlite3 --version

首先登陆到 sqlite 的官方下载地址,查看最新发布的版本,截止到本教程完成时,其最新版本为 3.29.0,找到该版本的源码压缩包,复制其下载链接,然后通过 wget 命令下载到服务器(我一般习惯将源码放在 ~/src 目录下。)

# 创建 src 目录并进到这个目录
$ mkdir -p ~/src
$ cd ~/src
# 下载 sqlite3 源码并解压安装
$ wget https://sqlite.org/2019/sqlite-autoconf-3290000.tar.gz
$ tar zxvf sqlite-autoconf-3290000.tar.gz
$ cd sqlite-autoconf-3290000
$ ./configure
$ make
$ sudo make install

至此 SQLite3 更新完毕,接下来安装 Python3。

安装 Python3 和 Pipenv

CentOS 7 自带的 Python 发行版为 2.7,因此需要安装 Python3,为了兼容性,我们安装 Python 3.6.4。

首先安装可能的依赖:

$ sudo yum install -y openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel

然后下载 Python 3.7.1 的源码并解压:

$ cd ~/src
$ wget https://www.python.org/ftp/python/3.7.1/Python-3.7.1.tgz
$ tar -zxvf Python-3.7.1.tgz

最后编译安装:

$ cd Python-3.7.1
$ ./configure LD_RUN_PATH=/usr/local/lib LDFLAGS="-L/usr/local/lib" CPPFLAGS="-I/usr/local/include"
$ make LD_RUN_PATH=/usr/local/lib
$ sudo make install

注意这里安装 Python 时,Python 会依赖 SQLite3 的库,所以在 configure 时通过 LD_RUN_PATH 指定依赖的搜索目录(因为我们之前更新了 SQLite3 的版本,指定依赖搜索目录确保使用新的 SQLite3 依赖库),另外两个参数作用类似。

然后输入 python3.7 -V 和 pip3.7 -V 命令测试安装结果,输出版本号说明安装成功了。

有了 pip,就可以安装 Pipenv 了:

$ sudo pip3.7 install pipenv

部署代码

打开 settings.py,找到 ALLOWED_HOSTS,将其修改为:

xxxproject/settings.py

ALLOWED_HOSTS = ['127.0.0.1', 'localhost ', '.yourdomain.com']

在面板中新建全静态站点,直接将本地项目文件上传至站点根目录。然后进入到项目根目录,安装项目依赖:

$ pipenv install --deploy --ignore-pipfile

这里指定 --deploy 参数,Pipenv 将只会安装 Pipfile 中 [packages] 下指定的依赖。因为我们现在是在线上环境进行部署,仅用于开发环境的相关依赖我们并不需要。--ignore-pipfile 将会使 Pipenv 从 Pipfile.lock 文件中安装项目依赖。Pipfile.lock 记录了项目依赖的精确信息,从这里读取依赖信息能够确保依赖信息被无意中修改或者破坏而使得运行环境因为依赖包的缘故出现不可预料的问题。Pipenv 会自动帮我们创建虚拟环境,然后将项目依赖安装到虚拟环境下。

这里把数据库文件一并上传至服务器,可直接运行开发服务器。如果不上传数据库,则需要创建数据库:

$ pipenv run python manage.py migrate

启动开发服务器:

$ pipenv run python manage.py runserver 0.0.0.0:8001

这里我们启动开发服务器时指定了服务器运行的 ip 和端口,这将允许通过公网 ip 的 8001 端口访问我们的博客。访问 ip:8001,可以看到访问成功。

管理开发服务器进程

使用Supervisor。先按 Ctrl + C 停止刚才启动的服务进程。

首先安装 Supervisor。注意这里使用的是系统自带的 pip2,因为截至本教程书写时 Supervisor 还不支持 Python3,不过这并不影响使用。

$ pip install supervisor

为了方便,我一般会设置如下的目录结构(位于 ~/etc 目录下)来管理 Supervisor 有关的文件:

~/etc
 
├── supervisor
│   ├── conf.d
│   └── var
│       ├── log
└── supervisord.conf

其中 supervisord.conf 是 Supervior 的配置文件,它会包含 conf.d 下的配置。var 目录下用于存放一些经常变动的文件,例如 socket 文件,pid 文件,log 下则存放日志文件。

首先来建立上述的目录结构:

$ mkdir -p ~/etc/supervisor/conf.d
$ mkdir -p ~/etc/supervisor/var/log

然后进入 ~/etc 目录下生成 Supervisor 的配置文件:

$ cd ~/etc
$ echo_supervisord_conf > supervisord.conf

修改 supervisor.conf,让 Supervisor 进程产生的一些文件生成到上面我们创建的目录下,而不是其默认指定的地方。

首先找到 [unix_http_server] 版块,将 file 设置改为如下的值:

[unix_http_server]
file=/root/etc/supervisor/var/supervisor.sock

即让 socket 文件生成在 ~/etc/supervisor/var/ 目录下。注意要用绝对路径指定。

类似的修改 [supervisord] 板块下的 logfile 和 pidfile 文件的路径,还有 user 改为系统用户,这样 supervisor 启动的进程将以系统用户运行,避免可能的权限问题:

logfile=/root/etc/supervisor/var/log/supervisord.log
pidfile=/root/etc/supervisor/var/supervisord.pid
user=root

还有 [supervisorctl] 板块下:

serverurl=unix:///root/etc/supervisor/var/supervisor.sock

[include] 版块,将 /root/etc/supervisor/conf.d/ 目录下所有以 .ini 结尾的文件内容包含到配置中来,这样便于配置的模块化管理。

files = /root/etc/supervisor/conf.d/*.ini

然后我们到 conf.d 新建我们博客应用的配置django1.ini

[program:django1]
command=pipenv run python manage.py runserver 0.0.0.0:8001
directory=/www/wwwroot/django1.yourdomain.come
autostart=true
autorestart=unexpected
user=root
stdout_logfile=/root/etc/supervisor/var/log/django1-stdout.log
stderr_logfile=/root/etc/supervisor/var/log/django1-stderr.log

启动 Supervisor

$ supervisord -c ~/etc/supervisord.conf

进入 supervisorctl 进程管理控制台:

$ supervisorctl -c ~/etc/supervisord.conf

执行 update 更新配置文件并启动应用,执行 status 可查看服务状态。

浏览器输入域名,可以看到服务已经正常启动了。

代码更新

停止应用

cd ~/etc/
supervisorctl stop program_name  # 停止某一个进程,program_name 为 [program:x] 里的 x

拷贝更新的文件至服务器项目根目录

# 安装依赖,迁移数据库
cd /www/wwwroot/django1.yourdomain.com
pipenv install --deploy --ignore-pipfile
pipenv run python manage.py migrate

重启应用:

cd ~/etc/
supervisorctl start program_name

域名设置

在宝塔面板的对应站点中设置反向代理,即可通过域名访问。