Django项目部署实战

部署Django项目,着实让人头大,虽然一个月之前耗时2天,终于部署成功一个项目,但到今天,部署项目时,按照记录的部署笔记,却仍然失败多次。抱着永不气馁的决心,从零开始部署,耗时1天,终于部署成功,虽然脑袋已经昏沉,却仍打开笔记,决定详细记录整个部署过程,以免遗忘。

软件

  • django 3.1.1
  • uWSGI 2.0.19.1
  • nginx
  • 腾讯云ubuntu S18
  • python3.6

步骤

  • 服务器搭建django虚拟环境
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
# 在虚拟环境下安装uWSGI
pip install uWSGI
  • uWSGI测试
# 在django项目跟目录下,新建一个test.py测试文件
# test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]
  • 运行uWSGI
uwsgi --http :8000 --wsgi-file test.py # 这步是为了验证uwsgi能否运行

# 在浏览器输入ip:8000 ,如果返回一个hello world,说明验证成功
# 如果验证不成功,那就找出问题,否则后面部署就无从谈起
  • 测试django项目
python manage.py runserver 0.0.0.0:8000 

  • django+uwsgi
# 当上面两项运行测试成功后,开始两者结合

uwsgi --http :8000 --module blog.wsgi   
# module 项目wsgi :加载指定的wsgi模块
# 这里是blog项目,在项目根目录运行
# 如果浏览器能够访问服务器,意味着uwsgi能够为虚拟环境中的django提供服务
# 以上操作,都是在虚拟环境中操作
# uwsgi 需要安装两次,一次是上面的虚拟环境中安装,第二次是全局安装,会在后续步骤中说明
  • 安装nginx
sudo apt install nginx # 全局安装,退出虚拟环境

# nginx 命令
sudo /etc/init.d/nginx start # 启动
                       restart # 重启
# 有多种命令 方式,这只是其中一种

# 安装完毕启动后,打开浏览器,默认80端口,可以看到welcome to nginx!
# 说明安装成功,如果80端口被其他服务占用,那就为nginx提供另一个端口

  • 配置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/
  • django部署静态文件
# 在settings.py中添加
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
# 运行
python manage.py collectstatic

  • nginx基本测试
# 重启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端口访问


  • 使用unix socket ,而不是端口
# 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 权限
# 这里需要修改nginx 的权限,修改sudo vim /etc/nginx/nginx.conf 文件
user www-data; # 第一行原内容
user 目前用的用户; # 把第一行注释掉,新增这句

  • 使用uwsgi和nginx运行django
uwsgi --socket blog.sock --module blog.wsgi --chmod-socket=664
  • 配置uwsgi以.ini文件运行
# 在项目根目录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用户一样
  • 最后一步 系统启动时运行uwsgi
# 系统启动时自动运行
# 编辑/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