Centos8.2下使用Docker-Compose+uWSGI+NGINX部署Django+Vue-cli项目

     阅读:23


前言

学习的文档:

docker-compose部署nginx+uwsgi+django项目:
https://blog.csdn.net/a914541185/article/details/103363599
vue + django 项目部署:
https://www.cnblogs.com/niehaidong111/p/11208492.html


一、部署流程

1、项目结构

项目框架:django项目文件夹中,包含vue_project的前端部分。
新增文件:

├── django
│   ├── Dockerfile
│   ├── docker_test.ini
├── docker-compose.yml
└── nginx
    ├── Dockerfile
    └── nginx-app.conf

环境说明:腾讯云CentOS8.2-Docker20,docker pull python和NGINX镜像
搭建完成后的项目结构:

├── django
│   ├── back.jpg
│   ├── db.sqlite3
│   ├── Dockerfile
│   ├── docker_test.ini
│   ├── manage.py
│   ├── master.pid
│   ├── myapp
│   ├── project_004
│   ├── requirements.txt
│   ├── run_cases.py
│   ├── scripts
│   └── vue_project
├── docker-compose.yml
└── nginx
    ├── data
    ├── Dockerfile
    └── nginx-app.conf

2、django目录下新建Dockerfile

此处使用python镜像制作django项目镜像。uWSGI包含在django项目目录内,所以需额外pip install uwsgi

FROM python:3.6

RUN mkdir /code

WORKDIR /code

COPY requirements.txt /code

RUN pip install uwsgi -i https://pypi.tuna.tsinghua.edu.cn/simple --default-timeout=200 \
    && pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --default-timeout=200 \
    && rm requirements.txt

EXPOSE 8000

3、编辑uWSGI文件

[uwsgi]
#http = 0.0.0.0:8000    #http协议,当不使用nginx的时候,使用这个来转发
# chdir = /code	#项目路径
#home = /root/code/Venv    #设置虚拟环境路径,需要可加上
module = project_004.wsgi:application
master = True
processes = 4
max-requests = 5000
harakiri = 60
socket = :8000	#端口号
chmod-socket=666
uid = root
gid = root
pidfile = /code/master.pid
#daemonize = /code/docker_test.log  #设置日志文件,这里不要加,docker容器需要进程在前台运行,加上日志会导致uwsgi转至后台
vacuum = True

注意:此处与教程不同,注释了chdir = /code #项目路径。若不注释,运行过程中出现了如下错误:

> *** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
chdir() to http=/home/Visualization/
chdir(): No such file or directory [core/uwsgi.c line 2625]

出现这种错误需要注释掉项目的路径
在这里插入图片描述

4、NGINX/Dockerfile配置

FROM nginx

MAINTAINER jc

EXPOSE 80 8000

5、NGINX/nginx-app.conf配置

upstream django{
         server web:8000;
}
server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        include /etc/nginx/uwsgi_params;
        uwsgi_connect_timeout 30;
        uwsgi_pass django;
        root   /code/vue_project/dist/;
        index  index.html index htm;
    }
    location /static/ {
        alias /code/vue_project/dist/static/; 
    }


    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

注意:nginx获取静态资源的路径需对应配置,否则部署完毕加载失败页面显示空白。
异常情况:
在这里插入图片描述

解决办法:

        root   /code/vue_project/dist/;  # vue-cli打包文件夹路径
        index  index.html index htm;
    }
    location /static/ {
        alias /code/vue_project/dist/static/;   # vue-cli打包文件夹路径
    }

6、docker-compose.yml

version: '3'

services:
  web:
    build: django
    restart: always
    privileged: true
    #端口映射
    ports:
      - "8000:8000"
    command: uwsgi --ini /code/docker_test.ini
    #挂载目录
    volumes:
      - ./django:/code

  nginx:
    container_name: nginx-container
    restart: always
    depends_on:
      - web
    links:
      - "web:web"
    build: nginx
    #端口映射
    ports:
      - "8888:80"
    #挂载目录
    volumes:
      - ./nginx/data:/var/log/nginx
      - ./nginx/nginx-app.conf:/etc/nginx/conf.d/default.conf
      - ./django/vue_project:/code/vue_project

注意:端口映射最好不要选择80映射80,存在80端口被占用情况

[root@VM-16-12-centos ~]# docker-compose up
Creating root_web_1 ... done
Creating nginx-container ... 
Creating nginx-container ... error

ERROR: for nginx-container  Cannot start service nginx: driver failed programming external connectivity on endpoint nginx-container (63c1061ab2f447ac698d992ded3a3faaa6965f45e784d6485952c4292f43f430): Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use

ERROR: for nginx  Cannot start service nginx: driver failed programming external connectivity on endpoint nginx-container (63c1061ab2f447ac698d992ded3a3faaa6965f45e784d6485952c4292f43f430): Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use
ERROR: Encountered errors while bringing up the project.

解决办法:
映射端口改为8888.

7、容器构建与启动

docker-compose build
docker-compose up

8、易错点说明

① 前端接口

前端的接口访问,不可写死为http://localhost:8000/get_devices/,也不可写死为http://外网IP:8000/get_devices/。
因添加了NGINX,接口调用处写函数名即可。

二、WSGI学习记录

1、WSGI

在这里插入图片描述
这里的uwsgi或者gunicorn扮演的角色就是web服务器的角色,这里的服务器是软件层面的服务器,用于处理浏览器发过来的HTTP请求以及将响应结果返回给前端。而Web框架的主要任务就是处理业务逻辑生成结果给web服务器,再由web服务器返回给浏览器。

而web框架和web服务器之间的通信需要遵循一套规范,这个规范就是WSGI了。

① Nginx+uWSGI

假设我们使用 Python 的 Django 框架写了一个网站,现在要将它挂在网上运行,我们一般需要:

Nginx 做为代理服务器:负责静态资源发送(js、css、图片等)、动态请求转发以及结果的回复。
uWSGI 做为后端服务器:负责接收 Nginx 转发的请求并处理后发给 Django 应用以及接收 Django 应用返回信息转发给 Nginx。
Django 应用收到请求后处理数据并渲染相应的返回页面给 uWSGI 服务器。

一个Django应用,通过WSGI协议连接uWSGI服务器,uWSGI服务器实现WSGI、http等协议,通过uwsgi协议和Nginx服务器实现http的动态请求和转发以及结果

②问题:有 uWSGI了,Django 为什么还需要 Nginx?

一个普通的个人网站,访问量不大的话,当然可以由 uWSGI 和 Django 构成。但是一旦访问量过大,客户端请求连接就要进行长时间的等待。这个时候就出来了分布式服务器,我们可以多来几台 Web 服务器,都能处理请求。

但是谁来分配客户端的请求连接和 Web 服务器呢?Nginx 就是这样一个管家的存在,由它来分配。这也就是由 Nginx 实现反向代理,即代理服务器。