前言:
目的:部署django项目至docker下 并实现nginx 反向代理与 uwsgi web 服务器任务分发,达到负载均衡的效果
现状:搜了很多网上的资料,有的不能用,有的环境不一样,有的玩不转。 既然自己弄通了就记录一下,写个完整版的部署过程
基础理论知识:
Nginx 反向代理服务器;
WSGI / Tomcat Web应用服务器;
Django Web应用框架(非服务器,MTV的框架模式,即模型M,模板T和视图V。)
正向代理与反向代理
正向代理:客户端(个人PC)通过 代理服务器,访问被限制的网络。 例如:访问google,学校网络授权软件,通过代理匿名访问,网络加速器等。
反向代理:服务器及网络 ,反向透明化。可以理解为 :客户端不需要更改任何代理配置,直接访问该网络,但不清楚自己访问的是不是对方原始ip地址,可能是网络映射。
反向代理作为接收请求,并转发给另一个地址资源的代理服务器。与正向代理区别于:来源未知,Sink对象已知。 而正向:个人PC Source 已知,Sink 未知。可能通过正向代理,访问了一个拥有反向代理的服务器。
Nginx :接收请求,反向代理到Tomcat , Tomcat 处理, 返回到Nginx,返回到 个人客户端。过程中,个人客户端只与Nginx 打交道,并不清楚Tomcat 的存在。
WSGI :用于连接Web服务器和Web应用框架
nginx 处理 static 任务 ,即django 下static 文件夹的文件。 其他事件交给uwsgi 处理
过程: PC -> Nginx -> WSGI -> Django -> WSGI -> Nginx -> PC
Django自带了wsgiref 作为wsgi服务器 ,但性能较 WSGI 还是有差距。本地测试 或小并发下没问题。
环境介绍:
CentOs 7
Docker version 18.09.9
Django 2.0.7
python:3.6.3
nginx latest
项目名:MyDemo
包含 static media MyDemo.settings uwsgi_conf.ini 以及各种webapp
前期准备:
拉取nginx镜像与python 镜像
docker pull nginx docker pull python
不放心的话可以本机Linux 下载 python/Django , runserver 先确保你的django 能run 。免得后续出问题理不清
单服务区版 正文:
Linux创建目录
mkdir /home/www/uwsgidocker
mkdir /home/www/uwsgidocker/nginxconf
vi Dockerfile
vi pip.conf
vi uwsgi_conf.ini
Dockerfile (uwsgi 镜像,也就是py-django镜像)
分别为py环境,项目路径, pip 加速镜像,依赖包(根据自己项目更改),uwsgi 启动器
FROM python:3.6.3
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY pip.conf /root/.pip/pip.conf
RUN pip install --upgrade pip
RUN pip install uwsgi
RUN pip install django==2.0.7
RUN pip install bs4
RUN pip install APScheduler==3.6.3
RUN pip install PyMySQL==0.9.2
RUN pip install diff-match-patch==20200713
RUN pip install django-apscheduler==0.3.1
RUN pip install django-crispy-forms==1.9.2
RUN pip install django-formtools==2.2
RUN pip install django-import-export==2.3.0
RUN pip install djangorestframework==3.11.1
RUN pip install docxtpl==0.10.0
RUN pip install future==0.18.2
RUN pip install numpy==1.19.1
RUN pip install pandas==1.1.1
RUN pip install plotly==4.9.0
RUN pip install pymssql==2.1.4
RUN pip install reportlab==3.5.49
RUN pip install six==1.15.0
RUN pip install django_crontab
RUN pip install pygments
RUN pip install httplib2
RUN pip install uwsgi
COPY . /usr/src/app/
CMD uwsgi --ini uwsgi_conf.ini
# 暴露端口
EXPOSE 80 8000 8822 8023
pip.conf(镜像下载加速)
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
uwsgi_conf.ini (uwsgi 服务器启动)
[uwsgi]
http = 0.0.0.0:8000 #单服务器只用http 就好
chdir = MyDemo
module = MyDemo.wsgi
processes = 1
master = True
vacuum = True
操作:该目录下 build and run uwsgi 镜像
docker build -t myuwsgi ./
docker run --rm -it --name webuwsgi -p 8000:8000 myuwsgi
此时浏览器访问带 8000/admin/ 的链接 应该是可以的。如果不行就先不要往后做了,好好梳理一下过程,不然后面做也是错的。
nginx 镜像
cd nginxconf/
Dockerfile
cat Dockerfile
FROM nginx
# 删除默认的nginx配置文件
RUN rm -rf /etc/nginx/conf.d/default.conf
# 将当前目录下的配置文件拷贝到/etc/nginx/conf.d/目录下
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY /static /static
EXPOSE 80
nginx.conf
server {
# 监听端口
listen 80;
# 主机名
server_name localhost;
location / {
include uwsgi_params;
proxy_pass http://172.17.0.2:8000; # 可通过 docker inspect webuwsgi
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /static {
# 静态文件
alias /static;
}
}
static 文件夹
将项目的static 静态文件夹移到此处,以便 nginx 使用。
Ps: static 包含 admin xadmin 等..
操作:该目录下 build and run uwsgi 镜像
docker build -t mynginx ./
docker run --rm -it -p 80:80 --name nginxweb mynginx
此时访问 本机ip地址 /admin (可不加端口号) 即访问 (中间如遇到 路径error 可根据自己的路径,灵活改变。 要么 run image 时 -v 引用 。 要么在Dockerfile 创建时就 COPY 进去。)
单服务器搭配完成
此套架构最大价值在于: 并发大时,nginx 识别请求,static 直接取。 其他事务转给uwsgi 。而任务分发在 nginx.conf 中。根据不同策略,分发至不同的 ,正在运行同一django 项目的docker 镜像服务器中。
下面介绍多镜像 负载均衡 架构。
多镜像介绍
2个 uwsgi (可无限增加)
1台 nginx
uwsgi
在但服务器跑通以后,cp 一份 备份 cp -r uwsgidocker uwsgidocker2
在 v2里搭建多镜像
Dockerfile 不变,修改 uwsgi_conf.ini ,更改通信方式
#http = 0.0.0.0:8000
socket = 0.0.0.0:8000
新建镜像
docker build -t myuwsgi2 ./
nginx
vi nginx.conf
新增
upstream django{
# server unix:///home/andrew/django/abuild/abulid.sock;
server 机器ip(非container ip):8022;
server 机器ip(非container ip)::8023;
}
django 可理解为数组名, 两台机器 分别暴露 8022 8023 端口
修改
location / {
include uwsgi_params;
uwsgi_pass django;
}
只留下这两个参数即可。django对应上面的数组名。(原始单服务器是指定固定ip 地址)
保存。新建镜像
docker build -t mynginx2 ./
集群测试:
docker ps
docker image ls
查看已存 image 应该有 python 3.6.3 nginx latest mynginx mynginx2 myuwsgi myuwsgi2
先启动 8022 和 8023 的 两台 uwsgi
docker run --rm -it --name testuwsgi2 -p 8022:8000 myuwsgi2
docker run --rm -it --name testuwsgi3 -p 8023:8000 myuwsgi2
在启动 n'gin'x
docker run --rm -it -p 80:80 --name nginxweb2 mynginx2
浏览器访问网页,测试 是否两台机器有响应
题外:nginx 分发策略可在 upstream 中编辑
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2、weight
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
3、ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
5、url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。