django项目部署与子域名配置

yuanheci 2025年01月11日 15次浏览

部署一下django后端项目,子域名的部署方式总是忘记,这里好好总结一下~

1. django部署

关于nginx和uwsgi和Django之间的关系,先梳理一下。

  • 为什么要用nginx
      因为我们要使用https协议访问。
  • uWSGI是什么
      uwsgi是一个Web服务器(类似于Java中的Tomcat服务器),它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uwsgi服务器进行交换。
      WSGI协议是Python 语言定义的 Web 服务器和 Web 应用程序或框架之间的一种简单而通用的接口。所以简单来说uWSGI就是用来沟通nginx和django的一座桥梁。
  • 为什么要nginx+uwsgi+diango这样来部署
      首先他们的工作流程是这样的:nginx 是对外的服务接口,外部浏览器通过url访问nginx。nginx 接收到浏览器发送过来的http请求,将包进行解析,分析url,如果是静态文件请求就直接访问用户给nginx配置的静态文件目录,直接返回用户请求的静态文件,如果不是静态文件,而是一个动态的请求,那么nginx就将请求转发给uwsgi,uwsgi 接收到请求之后将包进行处理,处理成wsgi可以接受的格式,并发给wsgi,wsgi 根据请求调用应用程序的某个文件,某个文件的某个函数,最后处理完将返回值再次交给wsgi,wsgi将返回值进行打包,打包成uwsgi能够接收的格式,uwsgi接收wsgi 发送的请求,并转发给nginx,nginx最终将返回值返回给浏览器。
      但是要知道第一级的nginx并不是必须的,uwsgi完全可以完成整个的和浏览器交互的流程。

那么nginx到底可以干嘛

  • 安全:程序不能直接被浏览器访问到,而是通过nginx,nginx只开放某个接口,uwsgi本身是内网接口,这样运维人员在nginx上加上安全性的限制,可以达到保护程序的作用。
  • 负载均衡:一个uwsgi很可能不够用,即使开了多个work也是不行,毕竟一台机器的cpu和内存都是有限的,有了nginx做代理,一个nginx可以代理多台uwsgi完成uwsgi的负载均衡。
  • 静态文件处理高效:用django或是uwsgi这种东西来负责静态文件的处理是很浪费的行为,而且他们本身对文件的处理也不如nginx好,所以整个静态文件的处理都直接由nginx完成,静态文件的访问完全不去经过uwsgi以及其后面的东西。这就是这几者之间的关系。

在我自己的django部署中:
  在启动了uWSGI服务后,就不能通过ip + 端口直接访问Django了,因为一旦启动uWSGI,所有的请求都会首先到uWSGI中,uWSGI会监听一些端口,在这里uWSGI监听的端口是本地的8000也就是127.0.0.1:8000,这也和我们构建的nginx连上了。总的模型是nginx<->uWSGI<->Django,uWSGI作为中间层。Nginx 向公网暴露的端口是443和80,分别是https和http,通过看y总的nginxconf文件,发现80的访问也就是http的访问都会重定位成https的访问,也就是nginx最终接受的https的访问情况,是安全的。在这里nginx充当了反向代理和解密的作用,反向代理可以简单的理解为一个门禁,处理https情况,处理高并发等问题,这里与后面有关的还有一个static的地方,nginx作为反向代理能更高效的处理静态文件,所以之后会有对static文件的打包。之后在进行解密从https到http, 加速通信速度和性能,在nginxconf文件中,nginx把请求放到本地的127.0.0.1:8000让uWSGI接受,这也和我们前面说的uWSGI监听的端口对应起来了,之后uWSGI把情况传给Django。这样一个流程就是请求的过程了,回应的过程也是一样的。uWSGI是应用服务器,主要是用于python应用和web服务器之间的通信,可以实现多线程和多进程和异步操作。


2. 系统部署方式

在一台服务器上用一个域名部署多个项目

yxc的做法是在docker中使用nginx,这样就把容器的80端口和443端口映射到宿主机,但是这样在单服务器上部署多项目时非常不便,耦合性非常大。宿主机的nginx无法运行。

解决方法1

  将该容器内部的nginx作为控制所有项目的大脑。即用容器内部的去转发所有的请求,配置你服务器上的多个项目。
image-1736594482186
当然,这不是一个好方式。。。接着看下面的~

解决方法2

将所有nginx配置写在宿主机的nginx中,让宿主机作为大脑去做统一转发。我当前使用的就是这个架构。
注意: 此时静态文件的路径需要加上容器本身在宿主机的路径,详细可参考:===> Java kob项目docker部署
image-1736594563064
该方式的问题在于宿主机的nginx配置较为复杂,维护有一定困难。

解决方法3

两层nginx代理
image-1736594700614
每一个项目都有自己独立的nginx配置,这样宿主机的nginx配置文件就能大大简化。从系统结构上来说这种模式解耦更好一点。
该做法需要1.解除容器对80端口的占用。
  因为nginx是默认运行在80端口,不同的两个nginx服务不能同时监听80端口。所以要将容器内的nginx的80端口映射到主机的其他端口上。443端口同理。
在不删除容器下改端口的方法:
修改文件:/var/lib/docker/containers/容器id/hostconfig.json
image-1736595028652

nginx是一个请求代理服务,它会监听和拦截某个端口的所有请求,实现控制转发和重定向。
image-1736595177038
对所有第二层的nginx来说,第一层nginx的地址是localhost。

image-1736595202301

配置宿主机上的第一层nginx
举例:

  	#项目一
  	server {
          listen 80;
          server_name appxxx.acapp.acwing.com.cn #或者是你自己的域名
          location / {
                        #这里的127.0.0.1指本机ip地址
               proxy_pass http://127.0.0.1:8000; #要代理转发的端口号
           }

      }
    #项目二
    server {
          listen 80;
          server_name yyy.xxx.com; #你的第二个二级域名
          location / {
               proxy_pass http://127.0.0.1:8080;
           }
      }

注意django和springboot部署,nginx中的配置是不同的,django会用到uwsgi。并且要注意对静态文件static的引用方式。

springboot+vue3项目,nginx配置:

	# xxx
    location / {
            root /home/acs/kob/web;
            index index.html;    
            try_files $uri $uri/ /index.html;
        }
     # xxx

django + jquery,nginx配置:

    # xxx
 location /static {
            alias /home/rsh/acapp/static/;
            xxx
  }
  # xxx

3. django项目部署

修改django项目的配置
打开 settings.py 文件 :
将分配的域名添加到 ALLOWED_HOSTS 列表中 (注意只需要添加 https:// 后面的部分)
DEBUG = False

归档 static 文件 :
python3 manage.py collectstatic
归档的目的是让 static 文件夹复制到 BASIC_DIR 下(之前在全局配置里改过的)

配置uwsgi
原来访问我们的 Django 项目,要通过访问网站的 8000 端口
配置好 uwsgi后,就可以直接通过 nginx 直接访问域名即可

在 django 项目中添加uwsgi的配置文件 : scripts/uwsgi.ini ,内容如下 :

[uwsgi]
socket          = 127.0.0.1:8000
chdir           = /home/acs/acapp
wsgi-file       = acapp/wsgi.py
master          = true
processes       = 2
threads         = 5
vacuum          = true

启动 uwsgi 服务 :
要事先关闭原来开启的 django 项目,然后再用 uwsgi 命令启动 django 项目
uwsgi --ini scripts/uwsgi.ini

总结:
django项目从开发模式转到线上模式,需要进行的操作:
一开始是用 python3 manage.py runserver 0.0.0.0:8000,使用django自带的单线程http服务器进行开发调试,此时配置好STATIC_ROOTSTATIC_URL,django框架就能自动找到这些静态文件并使用。可以通过ip:端口/static/…来在网页上查看这些文件。

DEBUG = False 时,表示不能默认找到这些静态文件了,需要用在nginx中配置路径进行查找。


4. 子域名的使用

对于子域名的使用老是出错,这里好好记录下。
使用子域名可实现一个宿主机部署多个不同域名的服务。对于我使用的免费SSL证书,一张证书只能用于一个域名,所以每个子域名都需要申请一张。(当然也有付费证书是一张能用于主域名及其下的所有子域名)
我用的是腾讯云,就以这个举例。
需要在云解析DNS界面中进行配置:
官方教程:https://cloud.tencent.com/document/product/302/105665

1、创建子域名
image-1736596434377

。。。(中间步骤看官方教程)
image-1736596549096

最后要记得在这里开启解析:
image-1736596513169