是时候让大家看看你用django写出来的博客了(内含部署教程视频)

10-14

浏览量:30

是时候让大家看看你用django写出来的博客了(内含部署教程视频)

作者:HelloGitHub- Dreamcatcher博客的基本功能已经开发的差不多了。虽然还有很多地方需要改进,但我们还是希望尽快将博客部署到服务器上,让其他人可以通过外网访问。至于需要改进的地方,部署后可以一点一点迭代改进。现在让我们将博客部署到服务器上!视频在这里。作者自己记录的真实机器环境演示了部署的全过程。如果你不成功,你会打我!b站演示(阿里巴巴云CentOS 7系统)观看地址:https://www.bilibili.com/video/av68020610/注:本文每一步都在真实环境中验证无误。除非你知道自己在做什么,否则建议你每一步都严格按照教程的指示去做,这样才能保证你能顺利完成部署。在部署之前,我们会将django开发的博客以Nginx Gunicorn的流行方式部署到我们自己的服务器上,这样其他人就可以通过域名访问你的博客了。至于什么是Nginx和Gunicorn,暂时放在一边。阅读本教程后,您将了解它们的功能和用法。为了部署我们的博客,我们需要满足以下两个条件:最好有一个可以通过外部网络访问的服务器(如果没有,我们可以在自己的计算机上构建一个虚拟机,并通过虚拟ip访问它)。最好有域名(如果没有,只能通过ip访问,不能打开HTTPS)。服务器配置本教程中使用的本地环境是Windows 10,服务器环境是CentOS 7(64位)。如果你的环境和我的不一样(比如Ubuntu),以至于有些命令无法执行,那就把这些命令转换成你环境的命令执行就行了。关键是要了解每一步的作用,这样就可以在任何环境下成功完成部署,而不是机械地复制粘贴命令。远程登录到服务器。服务器通常位于云中。您需要使用远程登录工具登录,然后才能操作服务器。我使用Xshell。百度Xshell可以在Windows下下载安装。该软件对学校和个人用户免费。这里不描述如何远程登录服务器。相信参考一些网上教程就可以顺利登录。如果你像我一样使用xshell,这里有一个非常详细的教程供参考:教你如何使用Xshell远程连接到linux服务器[2]。创建超级用户并成功连接到远程服务器。如果是全新的服务器,我们一般以root身份登录。在根目录下部署代码是不安全的。最好创建一个新用户(如果您以非根用户身份登录,可以跳过这一步)。下面的命令列表将创建一个具有超级权限的新用户(用你想要的用户名替换杨星,我这里取我名字拼音杨星):#在root用户下运行这个命令创建一个新用户,杨星就是用户名#因为我叫杨学光,所以我取用户名杨星#选择一个你喜欢的用户名,不一定要和我的一样。Root @ Server: ~ # AddUseryan。#为新用户设置密码#注意输入密码时不会显示任何字符,不要以为键盘坏了,正常输入即可。root @ server : ~ # passwdyanxing?#将新创建的用户添加到超级权限组root @ server : ~ # user mod-ag wheel yang?#切换到创建的新用户root @ server : ~ # su-yanxing?#成功切换,新用户名已经在@符号前面,而不是在root前面。yangxing @ server3360 $新用户已成功创建和切换。如果是新服务器,最好先更新系统,避免以后因为版本太旧而安装软件的麻烦。运行以下两个命令:gxg @ server : $ sudoyumpadatyangg @ server 3360 $ sudoyumpgrade update SQLite3为了方便起见,我们的博客使用了SQLite 3数据库。Django 2.2要求SQLite3数据库的版本在3.8.3以上,而CentOS 7系统的版本低于django 2.2要求的最低版本,所以先更新SQLite3的版本。请注意,您使用的服务器系统版本SQLite3可能高于3.8.3,因此可以跳过此步骤。

如何查看SQLite3的版本?请执行sqlite3 - version,首先登录sqlite的官方下载地址[3],查看最新版本。截至本教程完成,其最新版本为3.29.0。找到这个版本的源代码压缩包,复制它的下载链接,然后通过wget命令下载到服务器(我一般把源代码放在~/src目录下。#创建src目录并转到此目录yanxing @ server : $ mkdir-p ~/srcyangxg @ server 3360 $ CD ~/src?#下载s。

qlite3 源码并解压安装yangxg@server:$ wget https://sqlite.org/2019/sqlite-autoconf-3290000.tar.gzyangxg@server:$ tar zxvf sqlite-autoconf-3290000.tar.gzyangxg@server:$ cd sqlite-autoconf-3290000yangxg@server:$ ./configureyangxg@server:$ makeyangxg@server:$ sudo make install
小贴士:如果 wget 命令不存在,使用 sudo yum install -y wget 安装即可。
至此 SQLite3 更新完毕,接下来安装 Python3。安装 Python3 和 Pipenv CentOS 7 自带的 Python 发行版为 2.7,因此需要安装 Python3,为了兼容性,我们安装 Python 3.6.4。首先安装可能的依赖:
yangxg@server:$ sudo yum install -y openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel
然后下载 Python 3.6.4 的源码并解压:
yangxg@server:$ cd ~/srcyangxg@server:$ wget https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tgzyangxg@server:$ tar -zxvf Python-3.6.4.tgz
最后编译安装:
yangxg@server:$ cd Python-3.6.4yangxg@server:$ ./configure LD_RUN_PATH=/usr/local/lib LDFLAGS="-L/usr/local/lib" CPPFLAGS="-I/usr/local/include"yangxg@server:$ make LD_RUN_PATH=/usr/local/libyangxg@server:$ sudo make install
注意这里安装 Python 时,Python 会依赖 SQLite3 的库,所以在 configure 时通过 LD_RUN_PATH 指定依赖的搜索目录(因为我们之前更新了 SQLite3 的版本,指定依赖搜索目录确保使用新的 SQLite3 依赖库),另外两个参数作用类似。然后输入 python3.6 -V 和 pip3.6 -V 命令测试安装结果,输出版本号说明安装成功了。有了 pip,就可以安装 Pipenv 了:
yangxg@server:$ sudo pip3.6 install pipenv
小贴士:如果以上命令报错,可能是因为 pip3.6 安装在当前用户的 bin 路径下(/usr/local/bin/),使用 pip3.6 install pipenv --users 命令也把 Pipenv 安装到当前用户的 bin 路径下就可以了。
部署代码 接下来开始准备部署代码,让我们的博客应用在服务上跑起来,这和在本地开发时的过程是一模一样的。不过为了将应用部署到服务器上,我们首先要对项目做一点配置,打开 settings.py,找到 ALLOWED_HOSTS,将其修改为:
blogproject/settings.pyblogproject/settings.py?ALLOWED_HOSTS = ['127.0.0.1', 'localhost ', '.zmrenwu.com']
指定了 ALLOWED_HOSTS 的值后,django 将只允许通过指定的域名访问我们的应用,比如这里只允许通过 127.0.0.1,localhost 以及 zmrenwu.com 和其任意子域名(域名前加一个点表示允许访问该域名下的子域名)访问(即 HTTP 报文头部中 Host 的值必须是以上指定的域名,通常你在浏览器输入域名访问网站时,Host 的值就会被设置为网站的域名),这样可以避免 HTTP Host 头攻击。Django 项目中会有一些 CSS、JavaScript 等静态文件,为了能够方便地让 Nginx 处理这些静态文件的请求,我们把项目中的全部静态文件收集到一个统一的目录下,这个目录通常位于 django 项目的根目录,并且命名为 static。为了完成这些任务,需要在项目的配置文件里做一些必要的配置:
blogproject/settings.py?# 其他配置...?STATIC_URL = '/static/'# 加入下面的配置STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_ROOT 即指定静态文件的收集路径,这里指定为 BASE_DIR(项目根目录,在 settings.py 文件起始处定义)下的 static 文件夹。现在的关键是把代码传到服务器上来了,这里我们使用 git。首先安装 git:
yangxg@server:$ sudo yum install -y git
将代码上传到 GitHub 等代码托管平台,这样我们就可以方便地把代码拉取到服务器了。Git 和 GitHub 的使用相信你已经很熟悉了,这里就不赘述过程。如果不知道如何使用地话可以自行百度相关教程。注意数据库文件不要上传!我通常喜欢把应用代码放在 ~/apps/ 目录下,先来设置一下服务器的文件结构,用于存放应用代码等相关文件:
# 在用户目录下创建 apps 目录并进入yangxg@server:$ mkdir -p ~/appsyangxg@server:$ cd ~/apps?# 拉取博客代码yangxg@server:$ git clone https://github.com/HelloGitHub-Team/HelloDjango-blog-tutorial.git
然后进入到项目根目录,安装项目依赖:
yangxg@server:$ cd ~/apps/HelloDjango-blog-tutorial?yangxg@server:$ pipenv install --deploy --ignore-pipfile
这里指定 --deploy 参数,Pipenv 将只会安装 Pipfile 中 [packages] 下指定的依赖。因为我们现在是在线上环境进行部署,仅用于开发环境的相关依赖我们并不需要。--ignore-pipfile 将会使 Pipenv 从 Pipfile.lock 文件中安装项目依赖。Pipfile.lock 记录了项目依赖的精确信息,从这里读取依赖信息能够确保依赖信息被无意中修改或者破坏而使得运行环境因为依赖包的缘故出现不可预料的问题。Pipenv 会自动帮我们创建虚拟环境,然后将项目依赖安装到虚拟环境下。然后创建一下数据库:
yangxg@server:$ pipenv run python manage.py migrate
启动开发服务器:
yangxg@server:$ pipenv run python manage.py runserver 0.0.0.0:8000
这里我们启动开发服务器时指定了服务器运行的 ip 和端口,这将允许通过公网 ip 的 8000 端口访问我们的博客。访问 ip:8000,可以看到访问成功(其中 ip 为你服务器的公网 ip)。使用 Gunicorn Django 官方文档强调使用 runserver 开启的开发服务器仅用于开发测试,不建议用于生产环境。所以我们使用流行的 Gunicorn 来启动可以用于线上环境的服务器。首先进入到项目根目录,安装 Gunicorn:
yangxg@server:$ pipenv install gunicorn
由于我们在服务端修改安装了 gunicorn,代码中 Pipfile 文件和 Pipfile.lock 文件会被更新,因此别忘了把改动同步到本地,具体做法可以自行学习,以下是一个参考:
# 服务端提交代码yangxg@server:$ git add Pipfile Pipfile.lockyangxg@server:$ git commit -m "add gunicorn dependency"yangxg@server:$ git push?# 本地拉取代码git pull
回到线上服务器,在项目根目录,执行下面的命令启动服务:
yangxg@server:$ pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 0.0.0.0:8000
来解释一下各个参数的含义。`-w 2 表示启动 2 个 worker 用于处理请求(一个 worker 可以理解为一个进程),通常将 worker 数目设置为 CPU 核心数的 2-4 倍。-k gthread 指定每个 worker 处理请求的方式,根据大家的实践,指定为 gthread 的异步模式能获取比较高的性能,因此我们采用这种模式。-b 0.0.0.0:8000,将服务绑定到 8000 端口,运行通过公网 ip 和 8000 端口访问应用。访问 ip:8000(ip 为你服务器的公网 ip),应用成功访问了,但是我们看到样式完全乱了。别急,这不是 bug!此前我们使用 django 自带的开发服务器,它会自动帮我们处理静态样式文件,但是 Gunicorn 并不会帮我们这么做。因为处理静态文件并不是 Gunicorn 所擅长的事,应该将它交给更加专业的服务应用来做,比如 Nginx。启动 Nginx 服务器 Nginx (engine x) 是一个高性能的 HTTP 和反向代理 web 服务器,它的功能非常多,这里我们主要用它来处理静态文件以及将非静态文件的请求反向代理给 Gunicorn。当我们访问一个博客文章详情页面时,服务器会接收到下面两种请求:显示文章的详情信息,这些信息通常保存在数据库里,因此需要调用数据库获取数据。图片、css、js 等存在服务器某个文件夹下的静态文件。对于前一种请求,博客文章的数据需要借助 django 从数据库中获取,Nginx 处理不了,它就会把这个请求转发给 运行在 Gunicorn 服务中的 django 应用,让 django 去处理。而对于后一种静态文件的请求,只需要去这些静态文件所在的文件夹获取,Nginx 就会代为处理,不再麻烦 django。用 django 去获取静态文件是很耗时的,但 Nginx 可以很高效地处理,这就是我们要使用 Nginx 的原因。首先安装 Nginx:
yangxg@server:$ sudo yum install epel-release -yyangxg@server:$ sudo yum install nginx -y
运行下面的命令启动 Nginx 服务:
yangxg@server:$ sudo systemctl start nginx
在浏览器输入 ip(不输入端口则默认为 80 端口,Nginx 默认在 80 端口监听请求),看到 Nginx 的欢迎界面说明 Nginx 启动成功了。配置 Nginx Nginx 的配置位于 /etc/nginx/nginx.conf 文件中,你可以打开这个文件看看里面的内容,下面是一些关键性的配置:
user nobody nobody;...http { # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # 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 / { } }}
首先是这个 user 配置,用于指定 Nginx 进程运行时的用户和组(分别为第一个和第二个参数),为了防止可能的权限问题,我们改成当前系统用户(我的用户名是 yangxg,所属组 yangxg,记得改成你自己服务器中运行的用户和组,修改完后记得保存文件内容):
user yangxg yangxg;
然后在 http 配置下有一个 server 模块,server 模块用于配置一个虚拟服务,使这个虚拟服务监听指定的端口和域名。你可以配置多个 server,这样就会启动多个虚拟服务,用于监听不同端口,或者是同一个端口,但是不同的域名,这样你就可以在同一服务器部署多个 web 应用了。这个 server 的配置我们下面会详细讲解,再来看看 server 下的 include,include 会将指定路径中配置文件包含进来,这样便于配置的模块化管理,例如我们可以把不同 web 应用的配置放到 /etc/nginx/conf.d/ 目录下,这样 nginx 会把这个目录下所有以 .conf 结尾的文件内容包含到 nginx.conf 的配置中来,而无需把所有配置都堆到 nginx.conf 中,使得配置文件十分臃肿。我们来配置博客应用,上面说了,为了模块化管理,我们将配置写到 /etc/nginx/conf.d/ 目录下。先在服务器的 conf.d 目录下新建一个配置文件,我把它叫做 HelloDjango-blog-tutorial.conf。写入下面的配置内容:
server { charset utf-8; listen 80; server_name hellodjango-blog-tutorial-demo.zmrenwu.com;? location /static { alias /home/yangxg/apps/HelloDjango-blog-tutorial/static; }? location / { proxy_set_header Host $host; proxy_pass http://127.0.0.1:8000; }}
首先我们配置了一个虚拟服务,编码方式为 utf-8,监听于 80 端口。服务的域名为 hellodjango-blog-tutorial-demo.zmrenwu.com,所以来自这个域名的请求都会被这个服务所处理。所有URL 匹配 /static 的请求均由 Nginx 处理,alias 指明了静态文件的存放目录,这样 Nginx 就可以在这个目录下找到请求的文件返回给客户端。其它请求转发给运行在本机 8000 端口的应用程序处理,我们会在这个端口启动 Gunicorn 用于处理 Nginx 转发过来的请求。重启 nginx 使得配置生效:
yangxg@server:$ sudo systemctl restart nginx
关闭 DEBUG 模式,收集静态文件 开发环境下,django 为了调试方便,会将 settings.py 文件中的 DEBUG 选项配置为 True,这样如果程序运行出错,调试信息将一览无余,这在开发时很方便,但部署到线上就会带来巨大安全隐患,所以我们把 DEBUG 选项设置为 False,关闭调试模式,在本地将 settings.py 中的 DEBUG 为:
DEBUG=False
线上服务器更新最新的代码,然后运行命令收集静态文件到之前配置的 STATIC_ROOT 目录下:
yangxg@server:$ pipenv run python manage.py collectstatic
然后使用 Gunicorn 启动服务。
yangxg@server:$ pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 127.0.0.1:8000
现在,访问配置的域名 hellodjango-blog-tutorial-demo.zmrenwu.com(改成你自己在 Nginx 中配置的域名),可以看到博客成功部署!管理 Gunicorn 进程 现在 Gunicorn 是我们手工启动的,一旦我们退出 shell,服务器就关闭了,博客无法访问。就算在后台启动 Gunicorn,万一哪天服务器崩溃重启了又得重新登录服务器去启动,非常麻烦。为此使用 Supervisor 来管理 Gunicorn 进程,这样当服务器重新启动或者 Gunicorn 进程意外崩溃后,Supervisor 会帮我们自动重启 Gunicorn。先按 Ctrl + C 停止刚才启动的 Gunicorn 服务进程。首先安装 Supervisor 注意这里使用的是系统自带的 pip2,因为截至本教程书写时 Supervisor 还不支持 Python3,不过这并不影响使用。
yangxg@server:$ pip install supervisor
为了方便,我一般会设置如下的目录结构(位于 ~/etc 目录下)来管理 Supervisor 有关的文件:
~/etc?├── supervisor│ ├── conf.d│ └── var│ ├── log└── supervisord.conf
其中 supervisord.conf 是 Supervior 的配置文件,它会包含 conf.d 下的配置。var 目录下用于存放一些经常变动的文件,例如 socket 文件,pid 文件,log 下则存放日志文件。首先来建立上述的目录结构:
yangxg@server:$ mkdir -p ~/etc/supervisor/conf.dyangxg@server:$ mkdir -p ~/etc/supervisor/var/log
然后进入 ~/etc 目录下生成 Supervisor 的配置文件:
[unix_http_server]file=/home/yangxg/etc/supervisor/var/supervisor.sock
修改 supervisor.conf,让 Supervisor 进程产生的一些文件生成到上面我们创建的目录下,而不是其默认指定的地方。首先找到 [unix_http_server] 版块,将 file 设置改为如下的值:
[unix_http_server]file=/home/yangxg/etc/supervisor/var/supervisor.sock
即让 socket 文件生成在 ~/etc/supervisor/var/ 目录下。注意 supervisor 不支持将 ~ 展开为用户 home 目录,所以要用绝对路径指定。类似的修改 [supervisord] 板块下的 logfile 和 pidfile 文件的路径,还有 user 改为系统用户,这样 supervisor 启动的进程将以系统用户运行,避免可能的权限问题:
logfile=/home/yangxg/etc/supervisor/var/log/supervisord.logpidfile=/home/yangxg/etc/supervisor/var/supervisord.piduser=yangxg
还有 [supervisorctl] 板块下:
serverurl=unix:///home/yangxg/etc/supervisor/var/supervisor.sock
[include] 版块,将 /home/yangxg/etc/supervisor/conf.d/ 目录下所有以 .ini 结尾的文件内容包含到配置中来,这样便于配置的模块化管理,和之前 Nginx 配置文件的处理方式是类似的。
files = /home/yangxg/etc/supervisor/conf.d/*.ini
然后我们到 conf.d 新建我们博客应用的配置:
[program:hellodjango-blog-tutorial]command=pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 127.0.0.1:8000directory=/home/yangxg/apps/HelloDjango-blog-tutorialautostart=trueautorestart=unexpecteduser=yangxgstdout_logfile=/home/yangxg/etc/supervisor/var/log/hellodjango-blog-tutorial-stdout.logstderr_logfile=/home/yangxg/etc/supervisor/var/log/hellodjango-blog-tutorial-stderr.log
说一下各项配置的含义:[program:hellodjango-blog-tutorial] 指明运行应用的进程,名为 hellodjango-blog-tutorial。command 为进程启动时执行的命令。directory 指定执行命令时所在的目录。autostart 随 Supervisor 启动自动启动进程。autorestart 进程意外退出时重启。user 进程运行的用户,防止权限问题。stdout_logfile,stderr_logfile 日志输出文件。启动 Supervisor
yangxg@server:$ supervisord -c ~/etc/supervisord.conf
-c 指定 Supervisr 启动时的配置文件。进入 supervisorctl 进程管理控制台:
yangxg@server:$ supervisorctl -c ~/etc/supervisord.conf
执行 update 命令更新配置文件并启动应用。浏览器输入域名,可以看到服务已经正常启动了。使用 CDN 加快 Bootstrap 和 jQuery 的加载速度 我们的项目使用了 Bootstrap 和 jQuery,这两个文件我们是从本地加载的。如果服务器性能比较差的话,加载需要耗费很长的时间,网站打开的速度就变得无法忍受。我们使用 CDN 来加快加载速度。具体来说,替换 base.html 的几个静态文件的加载标签:
base.html?- - - + + + 
本地修改代码后,将代码同步到线上服务器,执行下面的命令重启 hellodjango-blog-tutorial 应用进程:
yangxg@server:$ supervisorctl -c ~/etc/supervisord.conf restart hellodjango-blog-tutorial
这样网站访问的速度将大大提升!总结 部署步骤很多且繁杂,因为每个环境都不一样,因此部署是最容易出错的步骤,一定要搞清楚每一步的作用,这样在遇到问题时,才能针对性地去解决,如果只知道一味地复制粘贴命令,而不知道自己在干嘛,那么一旦出错将束手无策。部署过程自动化 在整个部署过程中我们运行了十几条命令,手动输入了 N 个字符。如果每次更新代码都要远程连接到服务器执行这些命令的话将变得非常麻烦。接下来的教程我们将介绍使用 Fabric 自动化整个部署过程。写好部署脚本后,只需要执行一条命令,就可以非常方便地自动完成整个部署。References[1]HelloGitHub-Team 仓库: https://github.com/HelloGitHub-Team/HelloDjango-blog-tutorial[2]教你怎么使用 xshell 远程连接 linux 服务器:http://jingyan.baidu.com/article/ab69b270b0ca3d2ca7189fdc.html[3]sqlite 的官方下载地址: https://sqlite.org/download.html

『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎留言联系我们、加入我们,让更多人爱上开源、贡献开源~ 0
评论内容: