Docker部署Django综合项目

2018 年 10 月 22 日 • 阅读数: 132

Docker部署Django综合项目

这篇文章主要介绍了通过Docker来部署一个综合的Web项目,这个项目也就是这个博客网站本身

简介

一般来说我们可以直接把所有的应用部署到一个Centos容器中,然后直接运行这个Centos容器,内部通过Shell脚本来启动其他的应用,但这里我并没有这么做,而是分别构建Docker镜像,然后通过Docker-compose来管理编排所有容器

系统架构

luoyangc_jagou.png

从架构图中可以看出,我这里一共构建了4个容器:

  • Nginx容器:用于接收客户端的请求,然后静态请求直接处理,动态请求传给Web容器
  • Web容器:Web容器处理API数据请求,通过查询Mysql或者Redis的数据来进行响应
  • Redis容器:这里的Redis只是将不经常变动的API数据进行了缓存
  • Mysql容器:最主要的数据库,存储了包括用户数据,用户操作数据,文章数据等

Vue的打包

在创建Docker镜像之前我们需要对前端项目进行打包

注: 我使用的是Vue-cli3.0构建的Vue项目,一开始是没有配置文件的,所以需要先在根目录创建一个配置文件 vue.config.js ,所以的配置项都需要写在这里面

配置文件内容如下

module.exports = {

  // baseUrl  type:{string} default:'/' 项目目录
  baseUrl: '/',

  // outputDir: 在npm run build时 生成文件的目录 type:string, default:'disc'
  outputDir: 'disc',
  assetsDir: 'static',

  // lintOnSave:{ type:Boolean default:true } 是否使用eslint
  lintOnSave: true,

  // productionSourceMap:{ type:Bollean,default:true } 生产源映射
  productionSourceMap: false,

  // devServer:{type:Object} 3个属性host,port,https
  // 它支持webPack-dev-server的所有选项
  devServer: {
    port: 8080, // 端口号
    host: 'localhost',
    https: false, // https:{type:Boolean}
    open: true, //配置自动启动浏览器
    // proxy: 'http://localhost:8000' 配置跨域处理,只有一个代理
    proxy: {
      '/static': {
        target: 'http://127.0.0.1:8000/',
        ws: true,
        changeOrigin: true
      },
    },
  }
}

写好配置文件后,就可以通过 npm run build 打包项目了,它会根据配置文件中的 outputDir 在项目目录下生成一个最终打包的目录,将这个目录拷贝出来,放到Django项目的根目录中

注: 注意修改API以及组件中涉及到的URL地址,要改为线上的地址

Django的配置

在Django中,主要是要把模板文件的目录,和静态文件的目录指向我们刚才拷贝过来的Vue项目的打包目录中

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'disc')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "disc/static"),
)

**注:**同样要注意可以涉及到的URL地址,要改为线上的地址

Nginx容器的构建

Dockerfile的编写

FROM nginx

EXPOSE 80 8000

RUN rm /etc/nginx/conf.d/default.conf
ADD nginx.conf /etc/nginx/conf.d/

RUN mkdir -p /usr/share/nginx/html/static

RUN mkdir -p /usr/share/nginx/html/media

nginx.conf

server {
     listen      80;
     server_name localhost;
     charset     utf-8;
     error_log /tmp/nginx_error.log;
     access_log /tmp/nginx_access.log;
     location /media {
         alias /usr/share/nginx/html/media;
     }
     location /static {
         alias /usr/share/nginx/html/static;
         }
     location /admin/ {
     	 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header Host $http_host;
         proxy_redirect off;
         proxy_pass http://web:8000;
     }
     location / {
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header Host $http_host;
         proxy_redirect off;
         proxy_pass http://web:8000;
         index /static/index.html;
     }
}

Web容器的构建

看前面的架构图就知道,Web容器是比较复杂的一个容器,主要是Django需要WSGI来和Nginx等服务器通信,这里在Python中一般用来作为Web Server的有两个,一个是uwsgi,一个是gunicorn

这里我们使用第二种方式,关于gunicorn,这里不会详细介绍,这里只说我用到的地方

Dockerfile的编写

# 底层镜像依赖
FROM python:3.6
# 声明镜像作者
MAINTAINER "Luo Yang<1769570627@qq.com>"
# 设置时区
ENV TZ "Asia/Shanghai"

# 创建目录
RUN mkdir /luoyangc
# 设置系统环境变量DOCKER_SRC
ENV DOCKER_SRC=luoyangc
# 设置系统环境变量DOCKER_PROJECT
ENV DOCKER_PROJECT=/luoyangc

# 切换工作目录
WORKDIR $DOCKER_PROJECT

# 将当前目录加入到工作目录中
ADD . $DOCKER_PROJEdockerCT

# 安装应用运行所需要的依赖
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt

# 向外暴露端口
EXPOSE 8000

在Dockerfile中,安装依赖的时候使用到一个文件 requirements.txt requirements.txt 文件 里面记录了当前程序的所有依赖包及其精确版本号。这个文件的生成方式如下

pip freeze > requirements.txt

除此之外我们还需要写一个启动脚本 start.sh ,来启动Web服务,脚本文件如下

#!/bin/bash
python manage.py collectstatic --noinput &&
python manage.py migrate &&
gunicorn luoyangc.wsgi:application -c gunicorn.conf

这里我们使用了gunicorn来启动Django,同时加载了一个配置文件 gunicorn.conf ,配置文件如下

// 用于处理工作进程的数量,为正整数,默认为1
workers=4

// Gunicorn绑定服务器套接字,Host形式的字符串格式
bind=['0.0.0.0:8000']

// 要使用的工作模式,默认为sync,这里使用gevent,需要安装依赖,提前加入到requirements.txt中
worker_class='gevent'

// 重新启动之前,工作将处理的最大请求数。默认值为0
max_requests=6000

数据库的构建

Mysql的构建其实按理来说很简单,但是我在创建的时候出了一些问题,Django需要数据库的编码格式为UTF-8但是默认的创建的数据库并不是UTF-8,所以会出现编码错误,在启动Django服务的时候会报错

我的解决方式是运行一个Mysql的容器,然后进入到容器里面创建数据库设置数据库的编码格式,然后退出容器后,直接将这个容器打包成一个镜像,在下面创建容器的时候就直接使用自己打包的这个镜像去创建就行了

Redis就直接使用官方的镜像即可

注: 注意修改Django的数据库配置

# Mysql数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'luoyangc',
        'USER': 'root',
        'PASSWORD': '*',
        'HOST': 'db',
        'PORT': '3306',
        'OPTIONS': {'init_command': 'SET default_storage_engine=INNODB;'}
    }
}

# Redis数据缓存
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://redis:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

Docker-compose的构建

这个文件很重要,它是整个项目的入口,启动,停止,重启都需要依赖这个文件

version: "3"

services:
  db:
    image: luoyangc/mysql:1.0
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: *
    volumes:
      - ./srv/db:/var/lib/mysql
    restart: always
    networks:
      - luoyangc

  redis:
    image: redis
    restart: always
    networks:
      - luoyangc

  web:
    build: ./luoyangc
    ports:
      - "8000:8000"
    volumes:
      - ./luoyangc:/luoyangc
      - ./luoyangc/temp/logs:/tmp
    command: sh start.sh
    networks:
      - luoyangc

  nginx:
    build: ./nginx
    ports:
      - "80:80"
    volumes:
      - ./luoyangc/disc/static:/usr/share/nginx/html/static
      - ./luoyangc/media:/usr/share/nginx/html/media
    links:
      - web
    depends_on:
      - web
    restart: always
    networks:
      - luoyangc

networks:
  luoyangc:

和架构图一样,这里我一共构建了四个容器

db(Mysql数据库容器)配置的几个方面:

  • image:基础镜像,这里使用的我们上面手动构建的数据库,该数据库我也已经上传到Docker Hub中了
  • ports:主机和容器的端口映射,可以不写,我是为了方便在外部访问数据库,好进行数据同步才配置的
  • environment:配置了环境变量,这里是数据库的密码,和Django中的配置保持一致
  • volumes:数据卷,为了实现备份用的,/srv/db,是主机目录,/var/lib/mysql是MySQL容器内目录
  • restart:默认是no,意思是在任何情况都不会重启,如果设成always,就是如果stop了,就会重启
  • networks:将所以容器加入到一个虚拟网络中,(它自动也会做这一步…吗?)

redis(Redis缓存容器)

  • image:直接使用官方容器
  • restart:同上面一样
  • networks:同上面一样

web(Django应用容器)

  • build:根据Dockerfile重新build一个镜像
  • ports:这里我们需要暴露8000端口
  • volumes:同样是设置数据文件备份,也可以说成是同步,web容器的工作目录/blog备份到主机上的目录
  • command:启动容器执行的命令,这里我们执行了启动脚本
  • networks:同上面一样

nginx(服务器容器)

  • build:根据Dockerfile重新build一个镜像
  • ports:这里我们需要暴露80端口
  • volumes:同样是设置数据文件备份
  • links:创建和其他容器中的service的链接,有了network,这个应该不是必要的
  • depends_on:启动服务的时候,会先启动db,然后再启动web
  • restart:同上面一样
  • networks:同上面一样
操作 命令
启动服务 docker-compose up -d
停止服务 docker-compose down
重启服务 docker-compose restart

注: 其他命令请查看我的另一篇文章

标签: Docker服务器部署Django

召唤伊斯特瓦尔