• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Docker部署Django应用的示例

    之前部署Web应用,没用docker,直接在服务器上部署,使用了fabric+nginx+supervisor+gunicorn部署,可查看我写过的一片博客:部署Web应用。但后来了解了docker,为其“Build,Ship and Run Any App,Anywhere”的思想所折服,觉得这个太牛逼了,所以我也尝试一下自己用docker部署Web应用。本篇文章为了记录我用docker部署web应用的过程和心得。

    一、网络架构

    我用Visio大概画了一下我的网络架构图:

    我构建的容器:

    1. Nginx容器;
    2. Web server容器
    3. Redis容器
    4. memcached容器
    5. MySQL容器

    如果把所有应用都部署到一个应用中,可能会更简单,但不同容器之间就稍微复杂点。首先你要考虑好容器之间的依赖关系,比如nginx要依赖web服务器,如果web服务器不正常工作,那nginx就不能正常工作;web服务器要依赖于数据库等等;其次,要设置好容器间的数据共享问题。比如对于web应用的静态资源,怎么让nginx实现反向代理。

    带着这些疑问,开始部署。

    二、环境:

    准备docker的环境。

    对于docker的作用和介绍可参考官网:Docker service。

    要注意你的docker版本以及composefile版本,因为不同的版本,语法可能略有不同。我之前在配置共享数据卷的时候就遇到过坑,比如在version 3中删掉了volumes_from,我还不知道有版本差异,所以怎么配置都不对。更详细的请看官网:dockerfile 版本。

    1、工程结构

    ├── blog 
    │ ├── account
    │ ├── blog
    │ ├── dailyblog
    │ ├── Dockerfile
    │ ├── gunicorn.conf
    │ ├── manage.py
    │ ├── media
    │ ├── requirements.txt
    │ ├── start.sh
    │ └── static
    ├── docker-compose.yml
    └── nginx
     ├── Dockerfile
     └── nginx.conf

    blog是我的django应用,内有Dockfile文件;nginx文件里也有一个Dockfile。blog和nginx分别是一个service,我们通过docker-compose.yml文件的配置来创建镜像和容器。也就是说你必须要做几件事:

    1. 在每个服务(应用)下编写Dockerfile;
    2. 在docker-compose.yml文件中配置相关的服务;
    3. 执行docker-compose命令 build和up

    2、Django应用的配置(blog包):

    1)Dockfile

    FROM ubuntu:16.04
    
    #更新软件源,必须要执行,否则可能会出错。-y就是要跳过提示直接安装。
    RUN apt-get -y update
    
    RUN apt-get install -y python-dev python-pip
    RUN apt-get install -y python-setuptools
    #MySQL-Python必须得先安装这个库
    RUN apt-get install -y libmysqlclient-dev 
    RUN mkdir /blog
    #设置工作目录
    WORKDIR /blog
    #将当前目录加入到工作目录中
    ADD . /blog
    #install any needed pacakges in requirements.txt,你要把所有需要安装的Python模块加到这文件中。
    RUN pip install -r requirements.txt
    #对外暴露端口
    EXPOSE 80 8080 8000 5000
    #设置环境变量
    ENV SPIDER=/blog

    我的基础镜像选择了Ubuntu,是因为我觉得我可能更习惯一些。

    2)启动脚本 start.sh

    #!/bin/bash
    #命令只执行最后一个,所以用 &&
    
    python manage.py collectstatic --noinput &&
    python manage.py migrate &&
    gunicorn blog.wsgi:application -c gunicorn.conf

    在你初次部署时,你要收集各个app的static目录到工程static目录中,同时要创建数据库。上面的3个命令通过 && 拼接,相当于一个命令。

    此外,django应用选择gunicorn做web服务器,gunicorn的配置文件如下:

    workers=4
    bind=['0.0.0.0:8000']
    proc_name='blog'
    pidfile='/tmp/blog.pid'
    worker_class='gevent'
    max_requests=6000

    gunicorn中host选择 0.0.0.0:8000。

    3、Nginx配置(nginx目录)

    1)Dockfile

    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的基础镜像选择docker仓库中的基础镜像nginx即可,同时要把自己的配置文件添加到相关目录中。这里有一点要注意,就是我自己曾经在主机配置nginx的时候,一般/etc/nginx/nginx.conf会从 /etc/nginx/conf.d,和/etc/nginx/site-enabled/两个文件目录寻找conf文件,我之前都是添加到/etc/nginx/site-enabled/,这次也是这么做的,但是我配置运行之后,nginx没有正常工作,我进入nginx容器看了一下,想看看为啥我的配置没有加载,打开/etc/nginx/nginx.conf一看,果然,它只include了/etc/nginx/conf.d中的conf文件。Bingo!改了我的配置文件,OK。

    后面创建的static和media是为了web应用的静态文件存储。

    2)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 / {
      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;
     }
    
    }
    
    

    关于nginx配置,要注意以下两点,是非常重要的:

    location

    静态文件配置,nginx指定的静态文件原目录是在/usr/share/nginx/html/,而该目录下的静态文件是从web容器中通过volumes同步的。所以,等下docker-compose是非常非常重要的。

    proxy_pass

    这和你直接在主机上配置是不一样的,host不能写成具体的IP,要写服务名,这里要写web service的name,web是在docker-compose中定义的web应用的service名称。后面要写docker-compose的配置。

    4、docker-compose.yml配置

    version: "3"
    
    services:
    
    
     db:
     image: mysql
     environment:
      MYSQL_DATABASE: app_blog
      MYSQL_ROOT_PASSWORD: admin
     volumes:
      - /srv/db:/var/lib/mysql
     restart: always
    
     redis:
     image: redis
     restart: always
    
     memcached:
     image: memcached
     restart: always
    
     web:
     build: ./blog
     ports:
     - "8000:8000"
     volumes:
     - ./blog:/blog
     - /tmp/logs:/tmp
     command: bash start.sh
     links:
     - redis
     - memcached
     - db
     depends_on:
      - db
     restart: always
    
    
     nginx:
     build: ./nginx
     ports:
     - "80:80"
     volumes:
     - ./blog/static:/usr/share/nginx/html/static:ro
     - ./blog/media:/usr/share/nginx/html/media:ro
     links:
     - web
     depends_on:
     - web
     restart: always

     这个文件是非常重要的!!!

    定义了5个服务:

    服务名称对于容器间的沟通是非常重要的。我们这里一个一个说。

    1)db

    配置的几个方面:

    DATABASES = {
    'default': {
     'ENGINE': 'django.db.backends.mysql',
     'NAME': 'app_blog',
     'USER': 'root',
     'PASSWORD':'admin',
     'PORT':3306,
     'HOST':'db',
    }
    }
    

    2)redis,memcached

    这两个就一起说了,因为不需要重新配置,直接用仓库中的镜像即可。

    3)web应用

    配置的几个方面:

    4)nginx

    关于如何实现nginx容器和web容器间的数据共享,即静态文件共享的问题,真是把我困扰住了。我先是按照官网配置,在顶级配置了volumes,在服务下配置type,source,之类的,但一直没成功(如果有配成功的,拿出来分享下哈);后来网上搜了一堆资料,容器间共享他们都用了volumes_from,这在version3中已经取消了,退回旧版本还不行。上周五真是烦得我头疼啊。后来看了一篇文章,才突然开窍,我本应该早点想到啊。逻辑是这样的:

    首先,我在web应用中就已经设置volumes数据的备份,即将容器中的文件同步到主机上,然后主机就可以充当这个中间者,nginx容器再从主机上同步静态文件。这就相当于celery中,生产者将任务消息写到消息中间件中,然后消费者从中间件中取消息来消息,而这里面web应用就类似生产者,nginx是消费者。

    这样问题就迎刃而解了!!!

    到目前为止,所有部署相关的配置都已经写完了。

    首先执行:

    docker-compose build

    然后执行:

    docker-compose up -d 

    题外话:我是在周六晚上11点跑的第一个build命令,执行各种镜像下载,软件源更新,Get资源比较慢,我太困了,就睡觉了。晚上睡觉做梦感觉都是docker,然后不到6点我就起了,到了客厅看电脑build已经成功。我就开始执行up命令,当我打开浏览器,输入localhost,然后成功返回结果的那一刻,甭提多有成就感啦!!!

    随意几个知识点:

    Docker删除所有容器:

    docker rm docker ps -a -q

    最重要的是后面的 -q选项,表示只显示ID。

    删除none镜像:

    docker rmi docker images -f "dangling=true" -q

    更新。dockerfile要加上apt-get update,否则后面的命令不能正常执行;

    command命令只执行最后一个,在脚本中写了三个命令,但最后只执行最后一个。后来把三个命令用 && 拼接起来。

    docker镜像内的文件互相拷贝

    1、将本地文件拷贝到docker 镜像内

    docker cp /Users/howey/Documents/apache-maven-3.5.2/ 749056ea1637:/opt
    docker cp 本地路径 容器Id或name:容器目录

    2、将docker内文件拷贝到本地文件夹内

    docker cp 749056ea1637:/Users/howey/Documents/apache-maven-3.5.2 /opt/
    docker cp 容器Id:本地路径 镜像路径

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    上一篇:详解如何使用Docker部署一个web项目并打包成镜像文件
    下一篇:Docker service命令详解(小结)
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Docker部署Django应用的示例 Docker,部署,Django,应,用的,