vue+django项目部署
vue+django项目部署
vue+django项目部署
部署相关概念
项目服务器架构
我们希望别人能够访问到我们的项目,包括界面,以及处理客服端发过来请求的API,这就需要我们把项目放到公网上面。
一般的服务器架构如上图:
- 把vue客户端放到一个服务器中,供用户来访问静态页面。
- 把django服务器端放到另外一个服务器,为用户提供服务。但是会存在一个问题:开发的时候环境一般都是单线程的,而且django大概只支持4-5万的同时访问量(并发量),那么,如果只有一台django服务器,当有好多人来请求服务器的时候,服务器就崩溃了。解决放案就是把服务端分放在多个服务器中,分担高并发压力。把服务端分放在多个服务器上,又会产生一个问题:客服端发送的请求怎么知道它自己该访问哪一个服务器呢?这就需要在客户端搭建一个Nginx服务器来做请求转发,把这个问题交由Nginx来思考,后面会细讲Nginx。
- 把数据库单独存放在一个服务器上。根据实际的生产情况,我们得出结论:大部分项目中的数据库操作,90%为读操作,10%为写操作,且写操作一般是项目内部人员执行。因此,我们可以把数据库分成主库和从库,配置不同的性能,主库负责写,从库负责读,提升数据库性能。但是将数据库分库了,数据库之间怎么保证数据同步呢?这个问题需要下去查查。为了保证项目运行的稳定性,大公司还会有数据库集群操作,也就是当一组数据库服务器挂了,还有一组备用的服务器能够顶上来,使得服务没有中断期。
- 还可以有的划分是:静态文件服务器、Redis数据库服务器等~
反向代理
- 代理:客户端不能够直接找到服务器来处理自己的请求,代理就起到帮客户端查找服务器在哪里的作用。
- 正向代理:客户端把请求发送给代理,代理找到服务器并发请求转发服务器端,服务器把结果返回给客户端。这个流程就是正向代理,上左图。由于防火墙的原因,我们并不能直接访问谷歌,那么我们可以借助VPN来实现,这就是一个简单的正向代理的例子。这里你能够发现,正向代理“代理”的是客户端,而且客户端是知道目标的,而目标是不知道客户端是通过VPN访问的。
- 反向代理:客户端只向代理询问服务器在哪里而不把请求页转给代理,代理把服务器的位置告诉客户端后,
客户端自己发送请求给服务器。(前面是自己的理解)这个过程就是反向代理,上右图。别人的理解可能会更好一些:当我们在外网访问百度的时候,其实会进行一个转发,代理到内网去,这就是所谓的反向代理,即反向代理“代理”的是服务器端,而且这一个过程对于客户端而言是透明的。
前端部署
如果要让nginx运行起vue项目,需要将项目打包,生成原生的js代码。自动化程序会将打包的文件自动生成到项目的dist文件夹中:
npm run build
上面这个命令是用之前安装的webpack来进行打包的。
存在一个问题,每一次新的部署,我们都需要重新配置环境,安装这个软件、安装那个工具🔧,这样会很繁琐,项目维护起来也不是很方便,所以我们引入docker。它能够在容器中配置环境,就相当于一个操作系统,别人要运行我们的项目时,不需要再安装项目需求的依赖,只需要把我们的这个容器安装好,里面就自带了项目需要的依赖,很是方便。
docker
前面说了docker是拿来干什么用的,这里再说说docker的一些特点吧:
- “Build, Ship and Run”(搭建、运输、运行)
- “Build once,Run anywhere”(一次搭建,到处运行)
还是那句话,别人要运行你的项目的时候,直接安装你的docker就行了。
docker相关的概念如上图,我们在下面做一下讲解:
- 镜像:还没有运行起来的操作系统文件叫做镜像。每一个镜像中都包含了一个微型操作系统,但只会安装一些运行项目相关的依赖。我们可以从同事手中,或者开源社区获取到自己想要的镜像。自己也可以把自己创建的docker分享给别人。
- 容器:镜像运行的地方就是容器。这个容器我们不能提供给别人,但是我们可以进入这个容器进行一些相关依赖安装。就可以想象成一台电脑,我们能够在电脑上安装python 、c++、npm。在我们安装好相应的依赖之后,需要将当前的容器状态保存成镜像,这样我们又能够提供给别人了。
docker安装(mac)
根据教程安装成功。
使用常见命令
# 启动docker
sudo service docker start
# 停止docker
sudo service docker stop
# 重启docker
sudo service docker restart
# 列出镜像
docker image ls
# 拉取镜像
docker image pull library/hello-world
# 删除镜像
docker image rm 镜像id/镜像ID
# 创建容器,必须先有镜像,才能运行创建容器,如果不指定任何参数,容器开机了马上就回关机
docker run [选项参数] 镜像名 [命令]
# 例如:使用ubuntu镜像,创建一个名为ubuntu1
docker pull ubuntu:18.04
docker run -it --name=ubuntu1 ubuntu:18.04 bash
# 注意:必须启动的时候,让容器运行bash解析器,才能在接下来的操作让容器不会立刻关闭,而且也能够让我们可以输入linux终端命令, 如果我们一般创建一个容器,选项都是: -itd
# docker run的选项
# -t 表示容器启动后会进入其命令行终端
# -i 表示以“交互模式”运行容器
# --name 表示设置容器的名称
# -d 创建一个守护式容器在后台运行(这样创建容器后不会自动登录容器,如果只加-i -t 两个参数,创建后就会自动进去容器)
# 例如,使用ubuntu镜像,创建一个名为ubuntu2,并且在后台运行的容器像
docker run -itd --name=ubuntu2 ubuntu<:版本> ubuntu
# 进入容器,要进入容器,必须当前容器是启动状态的
docker container exec -it <容器名称/容器ID> <第一个命令>
# 所有正在启动运行的容器
docker container ls
# 所有容器[不管是否在启动运行中]
docker container ls --all
# 停止一个已经在运行的容器
docker container stop 容器名或容器id
# 启动一个已经停止的容器
docker container start 容器名或容器id
# kill掉一个已经在运行的容器
docker container kill 容器名或容器id
# 删除容器
docker container rm 容器名或容器id
# 把容器保存成镜像
docker commit <容器名称/容器ID> <新镜像名>
# 把docker中的镜像打包成文件,用于分享发送给他人,或备份
docker save -o <文件名.tar.gz> <镜像名>
# 把镜像文件加载到docker中
docker load -i <文件名.tar>
#官方提供的ubuntu系统镜像,工具命令很少,如希望内部安装ping、ifconfig网卡或者vim等工具,可以通过以下命令进行设置[需要联网,而且耗时]
apt-get update
apt install net-tools # ifconfig
apt install iputils-ping # ping
nginx
Nginx是一款基于异步框架的轻量级/高性能的Web 服务器/反向代理服务器/缓存服务器/电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like协议下发行。由俄罗斯的程序设计师Igor Sysoev(伊戈尔·赛索耶夫)所开发,最初供俄国大型网站Rambler.ru及搜寻引擎Rambler使用。有如下功能:
- 反向代理,前面说过了
- 因为可以反向代理,所以能够做负载均衡。所谓负载均衡就是在并发量很高的情况下,nginx可以让平均每个后端服务器接受的请求量。
- 热部署。所谓热部署,就是配置文件nginx.conf修改后,不需要stop Nginx,不需要中断请求,就能让配置文件生效!
下载安装nginx镜像
# 在docker中下载nginx镜像
docker image pull nginx
# 把前面使用npm run dev创建好的dist文件夹按下面的命令运行
# 创建nginx容器,并以80端口对外提供服务
# /usr/share/nginx/html 是nginx在安装时,系统默认分配的网站项目的根目录
docker run -itd -p 80:80 -v /home/luffy/lufei_pc/dist:/usr/share/nginx/html --name=lufei_pc nginx
# 执行上面的命令,理论上来说,就可以让前端项目在公网的IP地址访问到了。
其中docker run的参数值得说一说:
docker run 选项:
-v 目录映射,把服务器中的真实目录,映射到 容器内部的指定目录,当容器内部操作指定目录时,则相当于操作服务器里面的真实目录
-p 端口映射,把服务器中的真实端口,映射到 容器内部的执行端口,当用户访问/操作真实端口时,则相当于访问/操作容器里面的端口
上面部署命令之后,我们就可以通过IP来访问项目了,但是我们项目一般通过域名提供给用户来进行访问的。
域名解析
通过上面的步骤,我们可以通过访问IP地址来得到前端页面,但是如果有多个域名同时都指向这个服务器,则所有的域名都会访问到同一个项目中,所有我们把不同的域名和不同的项目目录进行配置绑定。这里就需要手动配置nginx的配置了:
# 进入nginx容器,修改/etc/nginx/conf.d/default.conf文件
# 要在容器里面编辑文件,可以通过 apt-get update 和 apt install vim 来安装一个编辑器。
docker container exec -it <容器名称/容器ID> bash
vim /etc/nginx/conf.d/default.conf
# 修改 server_name 对应的路径
server{
listen 80;
server_name 3w.lxh1.com;
# ...
}
# 按Esc键
# 输入 :wq 保存文件
# 重启nginx
nginx -s reload
后端部署
根据我们之前分析的项目部署架构,后端需要需要mysql和redis。所有再此我们需要先把这些外部工具先预装。
MySQL镜像
# 如果之前的mysql已经镜像没有下载,则下载命令如下:
docker image pull mysql:5.7
# -e 设置容器内部的环境变量,一个容器在创建的时候,可以多个不同的环境
# 启动mysql容器,MYSQL_ROOT_PASSWORD 指代的就是mysql的root用户的登录密码
docker run -itd -p3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
# 如果需要多台mysql容器安装在一台服务器中,那么容器内部的端口可以不用设置,但是真实物理系统的端口必须要修改,保证端口唯一!
# 我们可以在任意一个外部网路中,远程链接到数据库中
# 注意使用命令远程链接mysql,必须使用的地方有mysql
mysql -hIP -P端口 -uroot -p密码
# mysql -uroot -p123456 -h39.108.60.95
值得注意的是docker container run的选项:
-e 就是设置容器内部的环境变量, 在docker容器的使用过程中, 有部分容器需要配置环境的,这些环境变量都是有下载镜像时官方指定的。
接着把数据库中的数据导入到服务器的docker中:
# 远程链接数据库
mysql -uroot -p123456 -h39.108.60.95`在这里插入代码片`
# 创建数据库
create database luffy charset=utf8mb4;
exit
# 把本地的数据库导出到桌面
mysqldump -uroot -p123 luffy > ~/Desktop/luffy.sql
# 把桌面下导出的数据库文件导入到docker容器中的mysql数据库
mysql -uroot -p123456 -h39.108.60.95 luffy < ~/Desktop/luffy.sql
Redis镜像
# 因此我们需要在docker中下载redis和mysql的容器
docker pull redis
# 创建redis容器并运行redis
docker run -itd -p6379:6379 redis
# 可以进入到容器中,进行测试redis是否已经成功启动
docker container exec -it <容器名称/容器ID> bash
# 容器内部,执行 redis-cli
部署前处理
-
现在的配置,保存在dev.py中,不管数据库密码或者redis的地址或者配置信息都是属于开发阶段,项目上线以后,肯定换成公司的。所以一定会修改,我们需要把dev.py的内容移动到prod.py中,并修改对应的配置信息
-
在本地开发时,我们使用的框架运行在debug模式下的,但是项目上线时,会关闭debug,所以我们如果关闭了debug模式,则drf框架会不再提供静态文件的浏览服务,也就是之前xadmin,drf的接口页面的图片,样式或者js文件都不能访问到了。我们需要收集这些文件到外界,后面通过nginx来对外提供浏览服务
-
原来的drf项目是运行在python内置的提供的web服务器中,wsgiref
在项目上线的时候,我们不能使用这个模块来提供对外服务!不支持多线程,性能不好,本身在安全性上并不完善,python提供这个模块仅供学习和开发测试使用。runserver 不能用于生产,改成uwsgi -
原来drf项目在本地开发时,其实要运行这个项目,我们是安装了很多的以来模块。将来项目上线了,我们也肯定需要把本地的模块同步到线上服务器!否则项目跑不起来
从服务端项目中收集静态文件
当Django运行在生产环境中,我们会关闭debug调试,那么项目将不再提供静态文件的支持,需要将静态文件交给静态文件的nginx服务器来提供访问。
我们先收集所有静态文件。项目中的静态文件除了我们使用的上传文件之外,django本身还有自己的静态文件,如rest_framework、xadmin、admin、ckeditor等。我们需要收集这些静态文件,集中一起放到静态文件服务器中。
我们要将收集的静态文件放到项目的static目录中,所以先创建目录static。
Django提供了收集静态文件的方法。先在配置文件中配置收集之后存放的目录
settings/prod.py和dev.py ,代码:
STATIC_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'static')
因为目前在本地我们依然使用了dev.py文件运行项目,所以我们在本地项目收集静态文件就需要把配置信息同步到dev.py。
在终端下执行收集命令
python manage.py collectstatic
uwsgi服务器执行django项目
- 安装uwsgi
pip install uwsgi
uwsgi --version
- 修改配置
在luffyapi下的wsgi.py中修改:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'luffy.settings.prop')
- 配置uwsgi.ini
在项目根目录下创建uwsgi.ini,写入:
[uwsgi]
#使用nginx连接时使用,Django程序所在服务器地址
# socket=0.0.0.0:8000
#直接做web服务器使用,Django程序所在服务器地址
http=0.0.0.0:8000
#项目目录
chdir=/home/moluo/luffyapi
#项目中wsgi.py文件的目录,相对于项目目录
wsgi-file=luffycity/wsgi.py
# 进程数
processes=4
# 线程数
threads=2
# uwsgi服务器的角色
master=True
# 存放进程编号的文件
pidfile=uwsgi.pid
# 日志文件,因为uwsgi可以脱离终端在后台运行,日志看不见。我们以前的runserver是依赖终端的
daemonize=uwsgi.log
# 指定依赖的虚拟环境
virtualenv=/root/.virtualenvs/luffy
- 启动uwsgi服务器
uwsgi --ini uwsgi.ini
容器中配置运行环境
- 用
pip freeze
导出项目依赖,用pip install
在容器中安装相关依赖 - 安装好python等环境之后,使用
uwsgi --ini uwsgi.ini
来启动uwsgi,通过使用uwsgi作为http服务器先,后面再使用nginx来代理。
静态文件的访问支持
因为之前在前端项目部署的时候,已经有了一个nginx容器,所以我们接下来,就直接让前端的nginx容器同时提供静态文件的访问支持。进入前端nginx容器并在nginx的配置文件default.conf里面的server部分中配置提供静态文件的访问!先删除前端的vue项目的容器,然后再创建一个新的nginx容器,同时在创建的时候,我们进行目录映射。前端项目要映射到容器,同时还要把api项目的static静态文件目录也要映射到该容器中。
# 先把现有的前端nginx容器打包成镜像
docker commit lufei_pc front
# 停止并删除前端nginx服务容器
docker container stop lufei_pc
docker container rm lufei_pc
# 基于上面的front镜像重新创建一个容器。
# 真实服务器下的客户端vue项目目录 /home/luffy/lufei_pc/dist
# 真实服务器下的服务端drf项目目录 /home/luffy/luffyapi/static
docker run -itd -p 80:80 -v /home/luffy/lufei_pc/dist:/usr/share/nginx/html -v /home/luffy/luffyapi/static:/usr/share/nginx/static --name=lufei_pc front
创建完容器以后,通过访问客户端url地址,没有问题以后,我们接下里就要在前端容器中编写nginx的配置文件,写上提供静态文件访问支持的配置信息.配置文件default.conf,内容如下:
upstream luffy {
server 120.77.220.233:8000;
# server 120.77.220.233:8001;
}
server {
listen 80;
server_name api.lxh1.com;
location / {
include uwsgi_params;
uwsgi_pass luffy;
}
location /static {
root /usr/share/nginx;
}
}
server {
listen 80;
server_name 3w.lxh1.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
重启nginx,使用shop.lxh1.com访问运营后台,样式就正常了。
nginx -s reload.重启nginx,重新访问。
更多推荐
所有评论(0)