部署Django项目,着实让人头大,虽然一个月之前耗时2天,终于部署成功一个项目,但到今天,部署项目时,按照记录的部署笔记,却仍然失败多次。抱着永不气馁的决心,从零开始部署,耗时1天,终于部署成功,虽然脑袋已经昏沉,却仍打开笔记,决定详细记录整个部署过程,以免遗忘。
软件
- django 3.1.1
- uWSGI 2.0.19.1
- nginx
- 腾讯云ubuntu S18
- python3.6
步骤
python -m venv myenv # myenv虚拟环境名称
source myenv/bin/activate # 进入虚拟环境
pip install django
django-admin startproject blog # blog 项目
django-admin startapp article # 新建文章app
settings、createsuperuser # 设置、创建管理员这些内容省略
# 在虚拟环境下安装uWSGI
pip install uWSGI
# 在django项目跟目录下,新建一个test.py测试文件
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]
uwsgi --http :8000 --wsgi-file test.py # 这步是为了验证uwsgi能否运行
# 在浏览器输入ip:8000 ,如果返回一个hello world,说明验证成功
# 如果验证不成功,那就找出问题,否则后面部署就无从谈起
python manage.py runserver 0.0.0.0:8000
# 当上面两项运行测试成功后,开始两者结合
uwsgi --http :8000 --module blog.wsgi
# module 项目wsgi :加载指定的wsgi模块
# 这里是blog项目,在项目根目录运行
# 如果浏览器能够访问服务器,意味着uwsgi能够为虚拟环境中的django提供服务
# 以上操作,都是在虚拟环境中操作
# uwsgi 需要安装两次,一次是上面的虚拟环境中安装,第二次是全局安装,会在后续步骤中说明
sudo apt install nginx # 全局安装,退出虚拟环境
# nginx 命令
sudo /etc/init.d/nginx start # 启动
restart # 重启
# 有多种命令 方式,这只是其中一种
# 安装完毕启动后,打开浏览器,默认80端口,可以看到welcome to nginx!
# 说明安装成功,如果80端口被其他服务占用,那就为nginx提供另一个端口
# uwsgi_params 文件,其实etc/nginx 里面附带有这个文件
# 但为了能够确保部署成功,还是复制一份保存到项目根目录吧
# 之前部署成功的项目并没有保存在项目根目录
# include /etc/nginx/uwsgi_params;
# 如果复制到项目根目录,记得修改路径
# 在项目根目录,新建config 目录
# 新建 blog_nginx.conf 文件
upstream django {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
# configuration of the server
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
server_name .example.com; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# Django media
location /media {
alias /path/to/your/mysite/media; # your Django project's media files - amend as required
}
location /static {
alias /path/to/your/mysite/static; # your Django project's static files - amend as required
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed
}
}
# 将文件链接到 /etc/nginx/sites-enabled ,这里链接必须sudo ,全部绝对路径
sudo ln -s ~/path/to/your/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/
# 在settings.py中添加
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
# 运行
python manage.py collectstatic
# 重启nginx
sudo /etc/init.d/nginx restart
# 重启后,可能会遇到一些问题,通过 提示输入xxx status nginx.xxx 命令,可以查看错误内容
# 可以添加一个media.png图片到 项目/media目录中,通过网址
# http://xxxx/media/media.png 访问,成功说明nginx 提供了正确的文件服务
uwsgi --socket :8001 --wsgi-file test.py
# nginx 端口与uwsgi通信
# socket:8001 是uwsgi协议,端口为8001,而对外使用8000端口访问
# TCP端口socket简单,但开销大
# 使用unix socket 会比端口开销更少
# 编辑 blog_nginx.conf
server unix:///path/to/your/mysite/mysite.sock; # for a file socket
# server 127.0.0.1:8001; # for a web port socket (we'll use this first)
# 重启nginx ,再次运行uwsgi
uwsgi --socket blog.sock --wsgi-file test.py
# 如果错误,可以查看nginx错误日志 /var/log/nginx/error.log
connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission
denied)
# 这样的提示 是权限问题
uwsgi --socket blog.sock --wsgi-file test.py --chmod-socket=664 # (more sensible)
# 增加权限
# 这里需要修改nginx 的权限,修改sudo vim /etc/nginx/nginx.conf 文件
user www-data; # 第一行原内容
user 目前用的用户; # 把第一行注释掉,新增这句
uwsgi --socket blog.sock --module blog.wsgi --chmod-socket=664
# 在项目根目录config 里面新建blog_uwsgi.ini 文件
# 内容如下
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = /path/to/your/project
# Django's wsgi file
module = project.wsgi
# the virtualenv (full path)
home = /path/to/virtualenv
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10
# the socket (use the full path to be safe
socket = /path/to/your/project/mysite.sock
# ... with appropriate permissions - may be needed
# chmod-socket = 664
# clear environment on exit
vacuum = true
- 运行uswgi
uswgi --ini blog_uwsgi.ini
- 全局安装uWSGI
deactivate # 退出虚拟环境
sudo pip install uwsgi # 全局安装
- 再次检查运行uwsgi,不是在虚拟环境
uwsgi --ini blog_uwsgi.ini
- emperor 模式
# 每当修改配置文件,emperor将会自动重启vassal
sudo mkdir /etc/uwsgi
sudo mkdir /etc/uwsgi/vassals
# 这里链接仍然要绝对路径
sudo ln -s /path/to/your/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/
运行emperor
uwsgi --emperor /etc/uwsgi/vassals --uid xxx --gid xxx
# uid和gid后面的xxx 是指目前自己运行的用户,同nginx用户一样
# 系统启动时自动运行
# 编辑/etc/rc.local ,在exit 0 行前添加
/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data --daemonize /var/log/uwsgi-emperor.log
# 当然,里面的uid和gid 用户记得修改
到此部署完成
参考文档: https://uwsgi-docs-zh.readthedocs.io/zh_CN/latest/tutorials/Django_and_nginx.html