最近开发的一个django项目要求必须通过安全检测,必须采用https访问,因此,进行https相关的学习
由于商业证书要付费获取,这里采用openssl进行自签证书的获取。
在linux上安装openssl
yum install openssl -y
采用openssl获取证书,证书默认生成位置:/root
openssl
# 首先生成虚构的CA认证机构
genrsa -des3 -out ca.key 1024
rsa -in ca.key -out ca.key
req -new -x509 -key ca.key -out ca.crt -days 365
# 接着使用虚拟的CA认真机构生成证书
genrsa -des3 -out server.key 1024
req -new -key server.key -out server.csr
x509 -req -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt -days 365
【设置】-【隐私设置和安全性】-【安全】-【管理证书】,将server.crt导入
把server.crt、server.key证书复制到manage.py同级目录下
在settings.py中配置
SECURE_SSL_REDIRECT = True
INSTALLED_APPS = [
...,
'werkzeug_debugger_runserver',
'django_extensions',
]
安装相关依赖
pip3 install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple
pip3 install django-extensions -i https://mirrors.aliyun.com/pypi/simple
pip3 install django-werkzeug-debugger-runserver -i https://mirrors.aliyun.com/pypi/simple
pip3 install pyOpenSSL -i https://mirrors.aliyun.com/pypi/simple
启动django
python3 manage.py runserver_plus --cert server.crt 0.0.0.0:8001
然而,在浏览器打开网页的时候,报错静态文件找不到,404。
尝试采用另一个插件django-ssl
pip3 install django-sslserver==0.22
在settings.py中配置
SECURE_SSL_REDIRECT = True
INSTALLED_APPS = [
...,
'sslserver',
]
启动django,仍然报同样的静态文件404错误
python3 /opt/web/manage.py runsslserver 0.0.0.0:8001
考虑到生产环境部署时应当采用nginx来处理静态文件,尝试nginx+uwsgi部署
下载nginx镜像,在宿主机上建如图4个目录,
docker pull nginx
在宿主机上创建如下4个目录
docker run -d -p 80:80 --name nginx nginx
docker cp nginx:/etc/nginx/nginx.conf /opt/nginx/conf
docker cp nginx:/etc/nginx/conf.d /opt/nginx/conf
docker cp nginx:/usr/share/nginx/html /opt/nginx
关闭并删除已创建的nginx容器,将django中的静态文件dist放到html目录下,配置conf.d中的default.conf文件
# https版
server {
listen 80;
listen [::]:80;
# 这里有域名写域名,没有域名我写了ip地址
server_name <ip>;
# 开启https服务时,需要进行http的重定向
rewrite ^(.*) https://$server_name$1 permanent;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# 不开启https服务时,可以直接注释这个server
server {
listen 443 ssl;
# 这里有域名写域名,没有域名我写了ip地址
server_name <ip>;
# 这里指定ssl文件中的证书和key的位置
ssl_certificate /etc/nginx/ssl/development.crt;
ssl_certificate_key /etc/nginx/ssl/development.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 静态文件地址
root /usr/share/nginx/html/dist;
index index.html index.htm;
# uwsgi地址,ip根据实际情况填写
uwsgi_pass <ip>:8001;
include uwsgi_params;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
# http版
# 实现负载均衡
upstream web {
server <ip1>:8000;
# 多ip
# 若某一节点故障,从探查到故障的时刻开始,0-fail_timeout内,该节点会被排除
# server :8001 max_fails=1 fail_timeout=604800s;
# server :8002 max_fails=1 fail_timeout=604800s;
# 一定时间内同一个客户端的请求,由同一个节点处理
# ip_hash
}
server {
listen 80;
listen [::]:80;
server_name 10.30.239.195;
location / {
root /usr/share/nginx/html/dist;
index index.html index.htm;
include uwsgi_params;
uwsgi_pass web;
}
# 指定静态文件路径
# 否则会出现"GET /static/css/chunk-f660d60c.71ab5669.css HTTP/1.1" 404这样的静态资源访问错误
location /static {
# 指定静态文件存放的目录
alias /usr/share/nginx/html/dist;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
采用如下命令重新创建nginx容器,注意此处80(http)、和443(HTTPS)端口都要开启。
docker run -p 443:443 -p 80:80 --name nginx -v /opt/web/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /opt/web/nginx/conf/conf.d:/etc/nginx/conf.d -v /opt/web/nginx/log:/var/log/nginx -v /opt/web/nginx/html:/usr/share/nginx/html -v /opt/web/nginx/ssl:/etc/nginx/ssl/ -d nginx:latest
在生产环境中是这样的逻辑关系,个人理解:wsgi 是后端 http 服务器,nginx 是前端 http 服务器,django项目是客户所真正要访问到的提供数据方。因此还需要采用uwsgi来启动django
client–>NGINX–>uwsgi–>django
创建web容器
docker run -ti -p 8000:8000 -v /opt/145_graph/web:/opt/web --name 145_web_1 --privileged=true -t web:0 /bin/bash
在django项目的manage.py同级目录下创建uwsgi.ini文件,配置如下,启动命令
# 启动
uwsgi /opt/web/uwsgi.ini
# 停止
uwsgi --stop /opt/web/logs/uwsgi.pid
# 也可以通过kill进程方式停止
pkill -f uwsgi -9
[uwsgi]
; 监听的端口
; http = 0.0.0.0:8001
; 指定和nginx进行套接字通信的方式:端口或文件
socket = :8001
; 项目所在目录,和manage.py同级
chdir = /opt/web
; 主应用中的wsgi文件
wsgi-file = src/wsgi.py
; 代理静态资源:路径映射
static-map = /static=/opt/web/static
; 启动一个master进程,来管理其余的子进程
master=True
processes = 4
threads = 2
buffer-size = 65536
; 保存主进程的pid,用来控制uwsgi服务
pidfile=/opt/web/logs/uwsgi.pid
; 设置后台运行,保存日志
daemonize=/opt/web/logs/uwsgi.log
; 设置每个工作进程处理请求的上限,达到上限时,将回收(重启)该进程。可以预防内存泄漏
max-requests=5000
; 服务停止时自动移除unix Socket和pid文件
vacuum=true
如果uwsgi没有正确启动,打开网页的时候,nginx的error.log会报错
nginx和uwsgi启动完毕后,打开网页,https://,访问正常