• ubuntu+Docker双容器docker-compose部署Django+Vue项目(2-Django)


    部署Django后端接口

    下载Python环境及一些尝试

    由于项目用到是3.8.8版本,避免之后出现问题。就不下最新的了

    docker pull python:3.8.8
    
    • 1

    请添加图片描述
    python镜像启动一个容器,参数以命令模式进入该容器:

    docker run -it python /bin/bash
    
    • 1

    /bin/bash进入容器中的命令行,暂时我理解为进入之后用法和ubuntu中的终端一样。(毕竟一个容器相当于一个虚拟机[滑稽])
    但是上面的命令的命令会默认运行最新的python版本,本地的旧版本都不行
    运行指定版本镜像

    docker run -it python:3.8.8 /bin/bash
    
    • 1

    请添加图片描述
    后台运行
    在大部分的场景下,我们希望 docker 的服务是在后台运行的,我们可以过 -d 指定容器的运行模式,--name给容器起名

    docker run -itd  --name pythonTest python:3.8.8 /bin/bash  
    
    • 1

    在这里插入图片描述
    进入容器
    exec 命令适用于进入后台运行的容器

    docker exec -it 容器ID /bin/bash
    
    • 1

    可以直接进入容器中下载Django,执行如下命令,第一次不行,第二次就好了

    pip install django
    
    • 1

    pip包管理

    在本地下载pip管理工具(可以下载其他工具试试,这里用pipreqs)

    pip install pipreqs
    
    • 1

    下载完执行命令

    pipreqs  --encoding=utf8  ./
    
    • 1

    导出文件到当前路径,后续可继续添加所需要的库
    请添加图片描述
    在这里插入图片描述

    运行项目容器

    先跑出项目容器

    docker run -it -d --name Djangotest -p 9001:9001 -v /home/andy/Web/Django:/home/andy/Web/Django python:3.8.8
    #-v /home/test:/home/test是将/home/test是将主机上的该目录挂载到容器内的home目录下(当然也可以使用docker cp命令)
    
    • 1
    • 2

    其他解释见第一节

    -v         用于挂载容器目录路径,内外共享目录,用法:-v 宿主机路径:容器路径
    
    • 1

    进入容器

    docker exec -it Djangotest bash
    
    • 1

    然后安装requirements.txt中的库,执行完再安装uwsgi

    pip install -r /home/andy/Web/Django/requirements.txt
    pip install uwsgi
    
    • 1
    • 2

    uwsgi运行项目

    uwsgi  --ini  /home/andy/Web/Django/pvsite_uwsgi.ini 
    
    • 1
    报错1(查询容器IP解决)

    在这里插入图片描述
    应该pvsite_uwsgi.ini中的IP配置有问题
    查看docker容器的IP

    docker inspect 99ef4b98f188(该容器ID)
    
    • 1

    请添加图片描述
    容器IP就是172.17.0.5
    修改pvsite_uwsgi.ini配置如下

    [uwsgi]
    
    #chdir=/home/andy/Documents/photovoltaic/photovoltaicsite   # 指定运行目录:项目根目录的绝对路径
    
    # 指定sock的文件路径,可以用端口或sock文件(Nginx监听的端口)
    socket = 172.17.0.5:9001
    # stats子系统允许您将uWSGI的内部统计数据导出为JSON, 在指定的地址上,开启状态服务
    #stats = 127.0.0.1:9999
    #载入wsgi-file
    wsgi-file = photovoltaicsite/wsgi.py
    
    #允许主进程存在(enable master process)
    master=true
    #设置最大工作进程数:将会生成4个进程, 每个进程有2个线程
    processes=4
    threads = 2
    #某个权限
    chmod-socket = 666  
    #退出时清除环境  
    vacuum=true  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    再次运行

    报错2(pvsite_uwsgi.ini文件配置socket还是http)

    invalid request block size:21573 (max 4896) …skip

    看样子能访问,但是uwsgi内部解析的数据包只能最大4k。
    看样子给pvsite_uwsgi.ini文件增加一条这个就行。(后续结合nginx应该不会出现这种问题)

    #设置用于uwsgi包解析的内部缓存区大小到64k。默认是4k。
    buffer-size = 65536
    
    • 1
    • 2

    在这里插入图片描述
    加完之后继续运行

    报错3(用http先)
    uwsgi_proto_uwsgi_parser(): Resource temporarily unavailable [proto/uwsgi.c line 40]
    
    • 1

    这个报错目前不清楚是为什么,在docker中测试了很久。我是按照这个地址192.168.80.128:9001去访问的。而这个地址和端口是Django+uwsgi容器运行直接映射的端口。
    知道为什么了,人都傻了。自己在pvsite_uwsgi.ini配置的socket = 172.17.0.5:9001。我部署的是socket不是http怎么能用浏览器去访问到了。要在nginx中去监听这个socket才能访问啊。socket改成http就可以了。

    用python manage.py runserver运行项目先

    运行到现在其实还没配置好数据库(直觉告诉我先python manage.py runserver运行成功,这些问题迎刃而解),先用python manage.py runserver启动项目。配置好数据库吧。

    Django项目在settings.py中先改成连接另外一个ubuntu里的mysql试试
    在这里插入图片描述

    报错4(下载cryptography库)

    出现了之前一样的问题。确实个package。

    bash RuntimeError: 'cryptography' package is required for sha256_password or caching_sha2_password auth methods

    按照下面下载之后就可以运行成功了。

     pip install cryptography
    
    • 1
    回到用uwsgi+django运行成功先

    先收集Django后台的资源,运行如下命令,在当前路径下会生成static文件夹保存网页需要的静态资源。

    python manage.py collectstatic
    
    • 1

    由于之前在Django中的settings配置过资源路径只需要pvsite_uwsgi.ini文件新增如下:

    #加上读取静态资源路径(Django后台的css文件等,不然没样式)
    static-map =/static=/home/andy/Web/Django/photovoltaicsite/static
    
    • 1
    • 2

    访问Django后台成功了
    请添加图片描述

    在uwsgi+django中加入nginx配置

    先将pvsite_uwsgi.ini配置的http= 172.17.0.5:9001。改成socket=容器IP:端口
    加上-d后台运行uwsgi -d --ini /home/andy/Web/Django/pvsite_uwsgi.ini

    然后运行nginx容器
    这里我用的是-v挂载宿主机的目录和文件,所以有点长。(后面完善直接打包镜像用更好的方法) 。别忘了最后的nginx镜像

    docker run -it -d --name Vuetest -p 8080:8080 -v /home/andy/Web/Vue/dist/:/usr/share/nginx/html/ -v /home/andy/Web/Vue/nginx.conf:/etc/nginx/nginx.conf  nginx
    
    • 1

    文件目录挂载

    #-v /home/andy/Web/Vue/dist/:/usr/share/nginx/html/
    #-v /home/andy/Web/Vue/nginx.conf:/etc/nginx/nginx.conf
    
    • 1
    • 2

    这里已经要开启另外的nginx容器了。双容器运行的话要进行通信(像两个独立的虚拟机)。下面用到docker-compose

    最终使用docker-compose双容器配置

    项目目录树

    /home/andy/web目录下的大致目录结构

    Web:.
    │  docker-compose.yml
    ├─Django
    │  │  Dockerfile
    │  │  uwsgi_params 
    │  └─photovoltaicsite
    │      │  manage.py
    │      │  pvsite_uwsgi.ini
    │      │  requirements.txt
    │      ├─photovoltaiccalculation
    │      │  │  admin.py
    │      │  │  api.py
    │      │  │  api_url.py
    │      │  │  apps.py
    │      │  │  models.py
    │      │  │  modelToJson.py
    │      │  │  tests.py
    │      │  │  views.py
    │      │  │  __init__.py
    │      │  ├─migrations
    │      │          
    │      ├─photovoltaicsite
    │      │  │  asgi.py
    │      │  │  settings.py
    │      │  │  urls.py
    │      │  │  wsgi.py
    │      │  │  __init__.py
    │      │  └─__pycache__         
    │      ├─static
    │      │  ├─admin
    │      │  │  ├─css            
    │      │  │  ├─fonts    
    │      │  │  ├─img          
    │      │  │  └─js                 
    │      │  └─rest_framework
    │      │      ├─css      
    │      │      ├─docs
    │      │      │  ├─css    
    │      │      │  ├─img  
    │      │      │  └─js        
    │      │      ├─fonts     
    │      │      ├─img     
    │      │      └─js
    │      │              
    │      └─upload
    │          └─headImg
    │                  20221027135148-4.png
    │                  20221206021825-1.png
    │                  
    ├─Mysql(这个项目我直接连接了另外一台虚拟机上的mysql)
    └─Vue
        │  Dockerfile
        │  nginx.conf
        └─dist
            │  favicon.ico
            │  index.html  
            ├─css     
            ├─fonts     
            ├─img      
            └─js            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    在windows下可以终端下用tree /f >tree.md生成目录树

    docker-compose.yml配置

    version: "3"
    
    networks: # 自定义网络(默认桥接), 不使用links通信 
      #proxy:
        #ipam:
          #config:
          #- subnet: 172.16.0.0/24 #由于默认bridge桥接网络,重启容器后ip地址会改变.固定IP
      django_network:
        driver: bridge
      vue_nginx_network:
        driver: bridge
    
    services:
      django:
        build: /home/andy/Web/Django # '.'代表当前目录
        #command: uwsgi  --ini  /home/andy/Web/Django/photovoltaicsite/pvsite_uwsgi.ini   # 容器启动后启动web服务器,执行多条指令用下面的
        command: bash -c 'python manage.py makemigrations&&python manage.py migrate&&uwsgi  --ini  /home/andy/Web/Django/photovoltaicsite/pvsite_uwsgi.ini'
        networks:
         - django_network
         #proxy:
          #ipv4_address: 172.17.0.5 #固定IP
        ports:       #暴露容器端口,与-p相同,但是端口不能低于60
          - "9090:9090"
        volumes:      #虚拟机挂载文件和目录到容器
          - /home/andy/Web/Django:/home/andy/Web/Django
        restart: always # always表容器运行发生错误时一直重启
    
      vue_nginx:
        build: /home/andy/Web/Vue
        ports:
          - "8080:8080"
          - "9001:9001"
        restart: always # always表容器运行发生错误时一直重启
        volumes:     #虚拟机挂载文件和目录到容器
          - /home/andy/Web/Vue/nginx.conf:/etc/nginx/nginx.conf
          - /home/andy/Web/Vue/dist/:/usr/share/nginx/html/
          - /home/andy/Web/Django:/home/andy/Web/Django
        networks:
          - vue_nginx_network
          - django_network #将vue_nginx_network加入到django的网络中
        depends_on: #此标签用于解决容器的依赖,启动先后问题。如启动应用容器,需要先启动数据库容器php:depends_on:- apache- mysql
          - django
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    最终Django文件配置

    Django下的setttings.py配置就不展示了。网上其他教程容易搜到

    requirements.txt文件配置
    Django==4.1
    djangorestframework==3.14.0
    PyMySQL==1.0.2
    django-cors-headers==3.13.0
    uwsgi==2.0.21
    cryptography==38.0.4
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    pvsite_uwsgi.ini文件配置
    [uwsgi]
    
    #chdir=/home/andy/Documents/photovoltaic/photovoltaicsite   # 指定运行目录:项目根目录的绝对路径
    
    # 指定sock的文件路径,可以用端口或sock文件(Nginx监听的端口)
    socket = 0.0.0.0:9090
    
    # stats子系统允许您将uWSGI的内部统计数据导出为JSON, 在指定的地址上,开启状态服务
    #stats = 127.0.0.1:9999
    #载入wsgi-file
    wsgi-file = photovoltaicsite/wsgi.py
    
    #允许主进程存在(enable master process)
    master=true
    #设置最大工作进程数:将会生成4个进程, 每个进程有2个线程
    processes=4
    threads = 2
    #某个权限
    chmod-socket = 666  
    #退出时清除环境  
    vacuum=true  
    #设置用于uwsgi包解析的内部缓存区大小到64k。默认是4k。
    buffer-size = 65536
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    Django下的Dockerfile文件配置
    # 建立  python:3.8.8 环境
    FROM python:3.8.8
    # 镜像作者andy
    MAINTAINER andy
    # 将项目文件拷贝到工作目录下(拷贝的主机内容,最好是相对路径)
    COPY Django/ /home/andy/Web/Django
    # 设置容器内工作目录
    WORKDIR /home/andy/Web/Django/photovoltaicsite
    # 在容器内安装django项目需要的库
    RUN pip install -r /home/andy/Web/Django/photovoltaicsite/requirements.txt
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    最终Vue文件配置

    dist文件是vue-cli中build项目得到的

    Vue下的Dockerfile文件配置
    # 设置基础镜像
    FROM nginx
    # 定义作者
    MAINTAINER andy
    # 将dist文件中的内容复制到 /usr/share/nginx/html/ 这个目录下面
    COPY dist/  /usr/share/nginx/html/
    COPY nginx.conf /etc/nginx/nginx.conf
    #-v dist/  /usr/share/nginx/html/
    #-v /home/andy/Web/Vue/nginx.conf:/etc/nginx/nginx.conf
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    Vue下的nginx.conf文件配置
    user www-data;
    worker_processes auto;
    pid /run/nginx.pid;
    include /etc/nginx/modules-enabled/*.conf;
    
    events {
    	worker_connections 768;
    }
    
    http {
    	sendfile on;
    	tcp_nopush on;
    	tcp_nodelay on;
    	keepalive_timeout 65;
    	types_hash_max_size 2048;
    	include /etc/nginx/mime.types;
    	default_type application/octet-stream;
    
    	##
    	# SSL Settings
    	##
    
    	ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    	ssl_prefer_server_ciphers on;
    
    	##
    	# Logging Settings
    	##
    
    	access_log /var/log/nginx/access.log;
    	error_log /var/log/nginx/error.log;
    
    	##
    	# Gzip Settings
    	##
    
    	gzip on;
    	#	Vue configuration
    	server {
    	listen   8080;     #配置访问时的端口号
    	server_name  192.168.80.129;
    	charset     utf-8;
    	client_max_body_size  75M;  #影响post文件的最大大小
    
    	location / {          #配置web静态资源
    		root /usr/share/nginx/html/;
    		index index.html;
    		add_header 'Access-Control-Allow-Origin' '*';
    		}
    	}
    
    #	uWSGi configuration
    	upstream django {
    	    server 192.168.80.129:9090; # for a web port socket (we'll use this first)
    	}
    	server {
    	listen   9001;     #配置访问时的端口号
    	server_name  192.168.80.129;
    	charset     utf-8;
    	client_max_body_size  75M;  #影响post文件的最大大小
    	
    	location /upload {        #配置媒体资源文件
    		expires 30d;
    		autoindex  on;
    		add_header Cache-Control private;
    		alias /home/andy/Web/Django/photovoltaicsite/upload;
    		}
    	location /static {      #配置静态资源文件
    		expires 30d;
    		autoindex on;
    		add_header Cache-Control private;
    		#alias /home/andy/Documents/photovoltaic/photovoltaiccalculation;
    		alias /home/andy/Web/Django/photovoltaicsite/static;
    	}
    	location / {          #配置uWSGI服务器 uwsgi_read_timeout 设置超时时间,太短容易产生504网关超时错误
    		include /etc/nginx/uwsgi_params;
    		uwsgi_pass django;
    		uwsgi_read_timeout 2;
    
    	}
    	}
    	include /etc/nginx/conf.d/*.conf;
    	include /etc/nginx/sites-enabled/*;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    请添加图片描述
    最后能成功运行。

    其他笔记

    Linux中echo命令的功能是写内容到标准输出。

    #echo hello world
    hello world
    
    • 1
    • 2

    给static文件夹及其子文件和子目录的所有权限(读写)给所有用户:(当前路径有static文件夹)

    chmod -R 777 static
    
    • 1

    写在最后

    由于初次使用Docker。这篇博客更像是个人的一个笔记(边做边记),可能写的不是很清晰。但是对ubuntu+Docker环境的部署还是会有一些参考价值。

    在部署完后之后。对个人也有一些开发上的思考。比如在访问前端项目时,如果出现一些网络错误或是莫名其妙的短暂性的跨域(Django中已经设置过cors解决跨域了,不知道为什么会间歇性出现这个报错。但却不影响功能)导致访问不到资源,此时网站应该给出一个响应,类似返回一个自定义404页面或是500页面。

    主要参考链接1
    主要参考链接2
    做完发现的一个比较完善的部署教程

  • 相关阅读:
    Linux——Shell脚本编程(1)
    node版本管理工具nvm的安装卸载与使用(windows)
    AI大模型:大数据+大算力+强算法
    利用ChatGPT提升测试工作效率——测试工程师的新利器(一)
    初学者必读:如何使用 Nuxt 中间件简化网站开发
    JVM常见面试题及详解
    外贸行业常用英文邮件模板分享
    java中分割字符串总结 - 超级无敌详细版本。不仅要熟悉各种方法还要做到灵活运用。
    我的递归从不爆栈
    谷歌翻译不能用了
  • 原文地址:https://blog.csdn.net/qq_44976531/article/details/128099643