docker-compose+postsql多容器部署django-vue项目

一、docker-compose安装

1、在安装好docker基础上,linux系统运行以下命令以下载 Docker Compose 的当前稳定版本

sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
要安装其他版本的 Compose,请替换 1.29.2。

2、将可执行权限应用于二进制文件、创建软连接、测试是否安装成功。

sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

3、docker-compose version测试是否安装成功

docker-compose+postsql多容器部署django-vue项目_第1张图片

 二、部署

Django + Uwsgi + Nginx + Postgres + Redis组合容器

本例中我们将使用docker-compose编排并启动4个容器,这个更接近于实际生成环境下的部署。

  1.  Django + Uwsgi容器:核心应用程序,处理后端请求
  2.  PostgreSQL 容器:数据库服务
  3.  Redis 容器:缓存服务
  4.  Nginx容器:反向代理服务并处理静态资源请求

这四个容器的依赖关系是:Django+Uwsgi 容器依赖 Redis 容器和 PostgreSQL 容器,Nginx 容器依赖Django+Uwsgi容器。为了方便容器间的相互访问和通信,我们使用docker-compose时可以给每个容器取个别名,这样访问容器时就可以直接使用别名访问,而不使用Docker临时给容器分配的IP了。

Docker-compose部署Django-vue项目路径树形图

pwd显示的目录:/home/edwin/docker_project/quotationBackend
该目录下的大致项目结构:
└── quotationBackend             # 常规Django项目目录
    ├── Dockerfile                      # 构建Django+Uwsgi镜像的Dockerfile
    ├── docker-compose.yml     # 核心编排文件
    ├── manage.py
    ├── quotationBackend          # Django项目配置文件
    │        ├── asgi.py
    │        ├── __init__.py
    │        ├── settings.py
    │        ├── urls.py
    │        └── wsgi.py
    ├── pip.conf                           # 非必需。pypi源设置成国内,加速pip安装
    ├── requirements.txt              # Django项目依赖文件
    ├── start.sh                            # 启动Django+Uwsgi容器后要执行的脚本
    ├── dist                                  # 前端vue打包后的文件
    └── uwsgi.ini                          # uwsgi配置文件
    ├── nginx
    │        ├── Dockerfile              # 构建Nginx镜像所的Dockerfile
    │        ├── log                         # 挂载保存nginx容器内日志log目录
    │        ├── nginx.conf             # Nginx配置文件
    │        ├── ssl                         # 如果需要配置https需要用到

下面正式开始部署:

第一步:编写Nginx镜像和容器所需文件

1、构建Nginx镜像所使用的Dockerfile如下所示:

FROM nginx

RUN rm -rf /etc/nginx/conf.d/default.conf && 
    mkdir -p /root/docker_project/frontend
# 第一句删除nginx容器内路径下的default.conf(可不删除)和创建存放前端项目的路径。
# -p 确保目录名称存在,不存在的就建一个。
COPY ./nginx.conf /etc/nginx    # 拷贝当前路径下的配置文件到nginx容器里。

2、Nginx的配置文件如下所示:

user  root root;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log warn;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    upstream django_backend {
        server django_web:9000;
    }
    server {
        listen       9001;
        server_name  localhost;   # 不能填宿主机IP
        charset utf-8;
        client_max_body_size 10M; # 限制用户上传文件大小
        location / {
            root   /root/docker_project/frontend;
            index  index.html index.htm;
        }
        location /api/{
            rewrite  ^/api/(.*)$ /$1 break;
            include   /etc/nginx/uwsgi_params;
            uwsgi_pass django_backend;
        }
    }
}

 第二步:编写Web (Django+Uwsgi)镜像和容器所需文件

1、构建Web镜像(Django+Uwsgi)的所使用的Dockerfile如下所示:

FROM python:3.7
# 镜像作者
MAINTAINER zt_9773

RUN mkdir -p /root/docker_project/quotationBackend

WORKDIR /root/docker_project/quotationBackend  # 指定工作目录,比较重要,一般挂载路径是基于此路径

# 可选:设置镜像源为国内,设置后会快很多
COPY pip.conf /root/.pip/pip.conf
# 将当前目录copy到工作目录中(. 表示当前目录)
COPY . /root/docker_project/quotationBackend

# 安装项目依赖、给start.sh可执行权限(用于后续启动uwsgi)
RUN pip install -r requirements.txt \
    && chmod +x ./start.sh

2、start.sh启动脚本文件内容如下所示

#!/bin/bash
python manage.py makemigrations &&
python manage.py migrate &&
uwsgi --ini uwsgi.ini && tail -f /dev/null

# tail空命令防止web容器执行脚本后退出

3、uwsgi.ini配置文件如下所示:文件没有配置python虚拟环境,用的是容器默认的环境,所以可不用配置。

[uwsgi]
socket=0.0.0.0:9000
chdir=/root/docker_project/quotationBackend/
module=quotationBackend.wsgi:application
master=true
processes=4
threads=2
vacuum=true
thunder-lock=true
enable-threads=true
pidfile=uwsgi.pid
daemonize = uwsgi.log

第三步:编写docker-compose.yml文件

定义了2个数据卷,用于挂载容器内动态生成的数据,比如postSQL的存储数据,redis生成的快照这样即使删除容器,容器内产生的数据也不会丢失。

我们还定义了3个网络,分别为nginx_network(用于nginx和web容器间的通信),db_network(用于db和web容器间的通信)和redis_network(用于redis和web容器间的通信)。

整个编排里包含4项容器服务,别名分别为redisdatabasenginx和django_web,接下来我们将依次看看各个容器的Dockerfile和配置文件。

我这里redis和数据库直接使用的官方镜像,没有配置文件,因为可以直接使用,所以就没有单独给redis和数据库编写Dockerfile文件。

version: "3"

# 自定义数据卷
volumes:
  postgres_vol:
  redis_vol:

# 自定义网络(默认桥接), 不使用links通信
networks:
  nginx_network:
    driver: bridge
  db_network:
    driver: bridge
  redis_network:
    driver: bridge

services:
  redis:
    image: redis
    networks:
      - redis_network
    volumes:
      - redis_vol:/data    # 以数据卷挂载给reids数据备份
    ports:
      - "6379:6379"
    restart: always

  database:
    image: postgres:12
    environment:
      POSTGRES_DB: quotationBackend    # 数据库名字,不存在会自动创建
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: 123456
    networks:
      - db_network
    volumes:
      - postgres_vol:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    restart: always

  django_web:
    build: ./
    expose:
      - "9000"
    volumes:
      - .:/root/docker_project/quotationBackend  # 挂载项目代码
    networks:
      - db_network
      - redis_network
      - nginx_network
    depends_on:
      - database
      - redis
    command: ./start.sh     # 启动uwsgi
    restart: always

  nginx:
    build: ./nginx
    ports:
      - "9001:9001"
    volumes:
      - ./dist:/root/docker_project/frontend     # 挂载前端vue打包后文件
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf   # 挂载配置文件
      - ./logs:/var/log/nginx    # 挂载日志
    networks:
      - nginx_network
    depends_on:
      - django_web
    restart: always

第四步:修改Django项目settings.py

主要几项配置需要修改如下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'quotationBackend',
        'USER': 'postgres',
        'PASSWORD': '123456',
        'HOST': 'database',    # docker-compose.yml中
        'PORT': '5432'
    }
}

DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'  # 用处后面问题总结中介绍

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://redis:6379",   # docker-compose.yml中
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            # 连接池数量,如果decode_responses不设置为True的话,
            # 使用get_redis_connection读取的数据是bytes,
            # 需要decode为utf-8
            "CONNECTION_POOL_KWARGS": {"max_connections": 100, "decode_responses": True},
            # "PASSWORD": "123456",
        }
    }
}

第五步:使用docker-compose 构建镜像并启动容器组服务

现在我们可以使用docker-compose命名构建镜像并启动容器组了。

# 进入docker-compose.yml所在文件夹,输入以下命令构建镜像
sudo docker-compose build
# 查看已生成的镜像和已经启动的容器
sudo docker images
sudo docker ps
# 启动容器组服务
sudo docker-compose up

如果一切顺利,此时你应该可以看到四个容器服务都已经成功运行了。此时打开你的浏览器,输入你服务器的ip地址或域名指向地址,你就应该可以访问你的网站拉。

 第六步:遇到的问题排错总结

1、Nginx容器排错

docker-compose+postsql多容器部署django-vue项目_第2张图片

Nginx报错nginx: [emerg] "user" directive is not allowed here in /etc/nginx/conf.d/nginx.conf:1。。路径有问题,我开始把nginx的配置文件copy到这里的路径下了。应该放在/etc/nginx路径下面。

nginx排错最重要的是查看Nginx的错误日志,还有重点检查端口,和uwsgi配套检查,基本就不会有问题。

2、Web容器排错

docker-compose+postsql多容器部署django-vue项目_第3张图片 (1)、上面问题为start.sh格式配置不对,在最前面加上 #!/bin/bash 即可。。另外一个常发生的错误是 docker-compose生成的web容器执行脚本命令后立刻退出(exited with code 0),在start.sh中加入tail -f /dev/null后容器服务可持续运行。

(2)、在运行start.sh迁移数据库时有报警导致容器退出。

django_web_1  | user.User: (models.W042) Auto-created primary 
key used when not defining a primary key type, 
by default 'django.db.models.AutoField'.
django_web_1  | HINT: Configure the DEFAULT_AUTO_FIELD 
setting or the UserConfig.default_auto_field attribute 
to point to a subclass of AutoField, e.g. 'django.db.models.BigAutoField'.

在玩新发布的 Django 3.2 时,我注意到一个警告,我以前在从 Django 3.1 迁移的网站上没有看到警告(警告)。models.W042
该警告在 Django 3.2 中引入了一个新功能,该功能允许更改 Django 自动添加的原数默认字段,如果您没有明确定义主字段。官方这样说的。

 我的django版本是3.2.8,所以需要在settings.py配置文件中加上这句DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'。

(3)、构建数据库时有个端口占用错误Error starting userland proxy: listen tcp4 0.0.0.0:5432: bind: address already in use。直接在root用户运行netstat -tanlp ,然后找到端口5432的PID。 kill PID即可。

(4)、在requirements.txt中删掉psycopg2包,只需要安装psycopg2-binary且可以不用指定版本直接安装最新版本。

The psycopg2 wheel package will be renamed from release 2.8; 
in order to keep installing from binary please use 
"pip install psycopg2-binary" instead. 

三、最后小结

 1、说一说ports和expose的区别。

  • ports是将端口暴露给宿主机,而expose是将端口暴露给和本容器通信的容器,这里是通过 networks通信。
  • 用法区别,语法格式如下。
ports:
  - "80:80"      # 绑定容器的80端口到主机的80端口
  - "9000:8080"  # 绑定容器的8080端口到主机的9000端口
  - "443"        # 绑定容器的443端口到主机的任意端口,容器启动时随机分配绑定的主机端口号
expose:
  - "3000"
  - "8000"  # 将当前容器的端口3000和8000暴露给link到本容器的容器。

2、容器数据卷volumes。

  • 作用就是实现容器和容器之间数据共享,容器和宿主机之间数据备份防止数据丢失
  • 匿名挂载和具名挂载:就是在指定数据卷的时候,不指定容器路径对应的主机路径,这样对应映射的主机路径就是默认的路径/var/lib/docker/volumes/中自动生成一个随机命名的文件夹(默认以id命名)。例如本例中docker-compose.yml中定义的redis_vol和postgres_vol,启动成功后可在宿主机看到挂载的路径/var/lib/docker/volumes 下面。这里命名为redis_vol叫具名挂载。不命名docker会默认以id命名叫匿名挂载。
  • 指定路径挂载:主容器文件所在路径:容器内路径。nginx的几个挂载都是指定路径挂载。
  • 注意:不能通信的两个容器之间不能共享数据

   待续

你可能感兴趣的:(docker,django,postgresql,redis,nginx)