zoukankan      html  css  js  c++  java
  • 使用dockerfile 搭建django系统(nginx+redis+mongodb+celery)

    背景

    有需求需要对django系统进行docker化,以达到灵活部署和容灾。该系统基于django 2.2版本开发,数据库采用mongodb,服务器使用nginx,因系统有部分异步任务,异步任务则采用clelery+redis实现。
    基于该需求,所采用的思路是:“基于ubuntu16.04”源镜像,根据dockerfile制作各个运行环境的镜像。因docker提倡单应用单镜像,故这里将django源代码程序作为一个镜像、mongodb作为一个镜像、nginx作为一个镜像、redis作为一个镜像。并最终使用docker-compose对这些镜像做编排。(假设当前已了解docker与docker-compose知识)

    实现

    下面就是一步步制作docker镜像了。关于各个镜像的Dockerfile模板,这里有一个非常好用的网站,可在网站中搜索自己感兴趣的项目,得到其Dockerfile。假设ubuntu16.04的源镜像及版本名为:ubuntu:16.04。
    首先我们在宿主机(宿主机为ubuntu16.04系统,用户为user)中建立一个父文件夹例如名为vs,其中的目录如下:

    mongodb_vs: 存放mongod的数据、配置文件与dockerfile文件;
    vsapp: 存放django系统的源代码、相关配置文件与dockerfile文件;
    redis_vs: 存放redis的配置文件与dockerfile文件;
    nginx_vs: 存放nginx的配置文件与dockerfile文件。

    1. mongodb镜像

    首先是mongodb镜像的Dockerfile,内容如下:

    FROM  ubuntu:16.04
    
    RUN apt-get update
    RUN apt-get install gcc -y
    RUN apt-get install g++ -y
    RUN apt-get install make -y
    RUN apt-get install wget -y
    
    # Install MongoDB.
    RUN 
      apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 && 
      echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' > /etc/apt/sources.list.d/mongodb.list && 
      apt-get update && 
      apt-get install -y mongodb-org && 
      rm -rf /var/lib/apt/lists/*
    
    # Define mountable directories.
    VOLUME ["/data/db"]
    
    # Define working directory.
    WORKDIR /data
    RUN mkdir bin && mkdir log
    COPY mongodb.conf ./bin/
    
    # Expose ports.
    #   - 27017: process
    #   - 28017: http
    EXPOSE 27017
    EXPOSE 28017
    
    # Define default command.
    # CMD ["mongod", "-f", "./bin/mongodb.conf"]
    

    Dockerfile解释:首先更新ubuntu的源,然后下载mongodb的安装包并安装;在镜像中定义了“/data/db”的数据卷路径,并在/data/路径下创建了bin文件夹与log文件夹(db文件夹与log文件夹分别用来存储mongodb的数据库和mongodb运行的log。bin文件夹用来存放mongodb的配置文件);将宿主机下的mongodb配置文件“mongodb.conf”文件拷贝到镜像中的bin文件夹下;暴露mongodb运行的相应端口。
    Dockerfile运行条件:要想运行该Dockerfile,需要有配置文件mongodb.conf的支持。在mongodb_vs文件夹下放入Dockerfile并创建一个文件mongodb.conf和一个data文件夹,data文件夹中有db和log两个空文件夹(db和log用来存储mongodb运行中的数据库和log)。整体目录如下:

    --mongodb_vs
      --Dockerfile
      --mongodb.conf
      --data
        --db
        --log
    

    mongodb.conf内容如下:

    # db path
    dbpath = /data/db/
    # log path
    logpath = /data/log/logs.log
    port = 27017
    # fork = true
    # auth = true
    

    以上内容中,fork表示是否在后台运行mongodb,auth表示mongodb是否要进行认证,目前我们先将这两个禁用掉。
    编译镜像:在mongodb_vs文件夹下运行如下命令:

    docker build -t mongodb:v1.0 .
    

    命令运行后若是没有报错,则会编译出一个名为:mongodb:v1.0的镜像。
    运行容器:在mongodb文件夹下运行如下命令:

    docker run -it --name mongodb_test -p 27017:27017 -p 27018:27018 -v /home/user/vs/mongodb_vs/data/db:/data/db -v /home/user/vs/mongodb_vs/data/log:/data/log mongodb:v1.0
    

    我们基于mongodb_vs镜像在前台运行了一个名为mongodb_test的容器,并将其端口与宿主机端口绑定,将mongodb产生的数据、log与宿主机进行映射。
    若无报错,则会进入到该容器中,在容器中运行命令:mongod -f ./bin/mongodb.conf --fork则会在后台启动开mongodb服务。我们可以在该容器中再输入mongo命令,若能正常进入到mongodb的shell中,则说明mongodb启动成功(也可用工具检验是否能连接到该mongodb实例)。

    2. 源程序镜像

    因该系统采用python的django框架完成。故需要系统有python环境。我们可以先基于ubuntu源镜像制作一个python3的镜像,再基于python3的镜像制作源程序镜像。
    制作python3的镜像方法有很多,这里列出一种供参考:
    python3.6.3的Dockerfile

    FROM  ubuntu:16.04
    
    RUN apt-get update
    
    RUN apt-get -y install gcc make zlib1g zlib1g-dev openssl libpcre3 libpcre3-dev
    
    RUN apt-get -y install libbz2-dev libsqlite3-dev libxml2-dev libffi-dev libssl-dev libxslt1-dev
    
    RUN apt-get -y install wget
    
    RUN apt-get -y upgrade
    
    RUN apt-get -y dist-upgrade
    
    RUN apt-get -y install bzip2
    
    RUN apt-get -y install python3-pip python3-dev
    
    RUN wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tar.xz
    
    RUN tar -xvf Python-3.6.3.tar.xz
    
    RUN cd Python-3.6.3 && ./configure && make -j 8 && make install
    

    运行构建命令:docker build -t python:v3.6.3 .即可制作出python3.6.3的镜像。
    下面就是制作源程序的镜像,制作之前还需要一些准备工作:

    a.

    将源程序代码放入到vsapp文件夹下,例如源代码项目名为:vscode(vscode子一级目录下有manage.py文件);为了使项目支持nginx,在vscode子一级目录下放入名为uwsgi_params文件,文件内容为:

    
    uwsgi_param  QUERY_STRING       $query_string;
    uwsgi_param  REQUEST_METHOD     $request_method;
    uwsgi_param  CONTENT_TYPE       $content_type;
    uwsgi_param  CONTENT_LENGTH     $content_length;
    
    uwsgi_param  REQUEST_URI        $request_uri;
    uwsgi_param  PATH_INFO          $document_uri;
    uwsgi_param  DOCUMENT_ROOT      $document_root;
    uwsgi_param  SERVER_PROTOCOL    $server_protocol;
    uwsgi_param  REQUEST_SCHEME     $scheme;
    uwsgi_param  HTTPS              $https if_not_empty;
    
    uwsgi_param  REMOTE_ADDR        $remote_addr;
    uwsgi_param  REMOTE_PORT        $remote_port;
    uwsgi_param  SERVER_PORT        $server_port;
    uwsgi_param  SERVER_NAME        $server_name;
    
    
    b.

    利用命令“pip freeze > requirements.txt”将源程序所需要的python依赖包都导出到requirements.txt文件中。并将该文件放入到vsapp文件夹下。我这里的requirements.txt内容如下,供参考:

    beautifulsoup4==4.6.0
    redis==2.10.6
    celery==3.1.26.post2
    celery-with-redis==3.0
    Django==2.2.2
    django-rest-framework-mongoengine==3.3.1
    jira==2.0.0
    ldap3==2.6
    mongoengine==0.17.0
    multi-key-dict==2.0.3
    mysqlclient==1.3.13
    pymongo==3.8.0
    python-jenkins==1.4.0
    requests==2.22.0
    requests-oauthlib==1.2.0
    requests-toolbelt==0.9.1
    sqlparse==0.3.0
    urllib3==1.25.3
    xlrd==1.2.0
    xlwt==1.3.0
    generic==0.3.1
    uWSGI==2.0.17.1
    djangorestframework==3.9.4
    
    c.

    因项目中使用了celery,故还要将celery的配置文件放入到vsapp中。在vsapp中建立名为celeryconf的文件夹,下载官方的两个脚本并放入到celeryconf中;在vsapp中建立名为celeryd的文件,并将以下内容存储到该文件中:

    # Names of nodes to start
    #   most will only start one node:
    CELERYD_NODES="worker1"
    #   but you can also start multiple and configure settings
    #   for each in CELERYD_OPTS (see `celery multi --help` for examples).
    #CELERYD_NODES="worker1 worker2 worker3"
    
    # Absolute or relative path to the 'celery' command:
    CELERY_BIN="/usr/local/bin/celery"
    #CELERY_BIN="/virtualenvs/def/bin/celery"
    
    # App instance to use
    # comment out this line if you don't use an app
    # 这里填写实际的项目中项目名
    CELERY_APP="vscode"
    # or fully qualified:
    #CELERY_APP="proj.tasks:app"
    
    # Where to chdir at start.
    # 这里填写项目中应用名在容器中对应的绝对路径,因编译镜像时我这里命名为/web/vscode/
    CELERYD_CHDIR="/web/vscode/"
    
    # Extra command-line arguments to the worker
    CELERYD_OPTS="--time-limit=300 --concurrency=8"
    
    # %N will be replaced with the first part of the nodename.
    CELERYD_LOG_FILE="/var/log/celery/worker1.log"
    CELERYD_PID_FILE="/var/run/celery/%N.pid"
    
    # Workers should run as an unprivileged user.
    #   You need to create this user manually (or you can choose
    #   a user/group combination that already exists, e.g. nobody).
    CELERYD_USER="root"
    CELERYD_GROUP="root"
    
    # If enabled pid and log directories will be created if missing,
    # and owned by the userid/group configured.
    CELERY_CREATE_DIRS=1
    
    

    若是想查看celery运行的log,可以在vsapp下建立一个名为celerywork.log的文件。
    关于celery的配置详情,可参考这篇博客

    d.

    因源程序中采用的是“nginx + uwsgi”搭建服务器端,故这里需要对uwsgi进行配置。在vsapp下建立名为vsapp_uwsgi.ini的文件。并在其中保存以下内容:

    # mysite_uwsgi.ini file
    [uwsgi]
    # Django-related settings
    # the base directory (full path)
    chdir           = /web/vscode
    # Django's wsgi file
    module          = vscode.wsgi
    # the virtualenv (full path)
    # home            = /var/local/bin/python3
    
    # process-related settings
    # master
    master          = true
    # maximum number of worker processes
    processes       = 4
    chmod-socket    = 666
    # 这里指定了与nginx对接的端口为8000
    socket          = :8000
    # clear environment on exit
    vacuum          = true
    uid             = www-data
    gid             = www-data
    pidfile         = /web/webapp_uwsgi.pid
    # daemonize       = /web/uwsgi_log.log
    
    e.

    下面就是配置源程序运行的启动命令。因源程序运行既需要启动uwsgi还需要启动celery的异步任务与定时任务。故我们在vsapp下建立名为run_web.sh的文件,并放入如下内容:

    #!/bin/bash
    
    # 启动celery的异步任务与定时任务
    /etc/init.d/celeryd start
    /etc/init.d/celerybeat start
    # 启动uwsgi
    uwsgi --ini vsapp_uwsgi.ini
    
    f.

    准备工作做完后,就是编写源程序的Dockerfile了。在vsapp下建立名为Dockerfile的文件,其中内容如下:

    FROM python:v3.6.3
    
    RUN apt-get update 
        && apt-get install -y libmysqlclient-dev 
        && apt-get install -y --no-install-recommends 
            postgresql-client 
        && rm -rf /var/lib/apt/lists/*
    
    VOLUME ["/web/vscode"]
    WORKDIR /web
    COPY requirements.txt ./
    RUN pip3 install -r requirements.txt
    
    COPY vsapp_uwsgi.ini ./
    COPY celeryconf/celeryd /etc/init.d/
    COPY celeryconf/celerybeat /etc/init.d/
    COPY celeryd /etc/default/
    COPY run_web.sh ./
    RUN chmod 777 run_web.sh 
        && chmod 777 /etc/init.d/celeryd 
        && chmod 777 /etc/init.d/celerybeat 
        && chmod 640 /etc/default/celeryd
    
    EXPOSE 8000
    # CMD ["./run_web.sh"]
    

    最后,整个vsapp下的目录如下:

    编译镜像:在vsapp文件夹下运行如下命令:

    docker build -t vsapp:v1.0 .
    

    运行容器:镜像编译成功后,运行如下命令:

    docker run -it --name vsapp_test -p 8000:8000 -v /home/user/vs/vsapp/vscode/:/web/vscode/ -p /home/user/vs/vsapp/celerywork.log:/var/log/celery/worker1.log
    

    若容器运行成功,在该容器中运行shell脚本命令“./run_web.sh”,即可启动源程序的服务,若期间没有报错,则源程序镜像制作成功。

    3. nginx镜像

    nginx镜像的制作只需要重新配置一下nginx的配置文件nginx.conf,以使其能够与源程序对接并加载源程序中的静态资源文件。
    在nginx_vs文件夹下创建名为nginx.conf的文件,该文件内容如下:

    #user www-data;
    worker_processes 1;
    #pid /run/nginx.pid;
    events {
      worker_connections  1024;  ## Default: 1024
    }
    
    http {
        # Definethe MIME types for files.
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
        upstream django {
            # server unix:///usr/share/nginx/html/webapp.sock;
            # 这里的端口要写成8000,因为在源程序镜像中的vsapp_uwsgi.ini中配置的是8000
            server 127.0.0.1:8000; # for a web port socket (we'll use this first)
        }
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
        fastcgi_buffer_size 256k;         
        fastcgi_buffers 16 256k;
        fastcgi_busy_buffers_size 512k;
        fastcgi_temp_file_write_size 512k;
    
        # configuration of the server
        server {
            # the port your site will be served on
            listen      8090;
            # the domain name it will serve for
            server_name 127.0.0.1; # substitute your machine's IP address or FQDN
            charset     UTF-8;
            access_log      logs/myweb_access.log;
            error_log       logs/myweb_error.log;
    
            # max upload size
            client_max_body_size 75M;   # adjust to taste
    
            # Django media
            location /static/ {
                expires 30d;
                autoindex on;
                add_header Cache-Control private;
                alias /usr/share/nginx/html/webapp/static/; # your Django project's static files - amend as required
            }
            # Finally, send all non-media requests to the Django server.
            location / {
                uwsgi_read_timeout 500;
                uwsgi_pass  django;
                include     /usr/share/nginx/html/webapp/uwsgi_params; # the uwsgi_params file you installed
            }
        }
    }
    daemon off;
    
    

    该配置文件其实是对原nginx中的配置文件进行了更改。主要是声明了内部nginx与uwsgi通讯的端口,以及外部正常访问服务器的端口;源程序的静态资源文件夹路径;源程序的的uwsgi_params文件路径。
    在nginx_vs文件夹下建立Dockerfile文件,内容如下:

    FROM  ubuntu:16.04
    
    
    RUN apt-get update
    RUN apt-get install gcc -y
    RUN apt-get install g++ -y
    RUN apt-get install make -y
    RUN apt-get install wget -y
    
    RUN wget http://nginx.org/download/nginx-1.14.0.tar.gz && wget https://ftp.pcre.org/pub/pcre/pcre-8.37.tar.gz
    
    #RUN cd /usr/local && mkdir src
    RUN tar -xvf nginx-1.14.0.tar.gz -C /usr/local/src && tar -xvf pcre-8.37.tar.gz -C /usr/local/src
    
    WORKDIR /usr/local/src/nginx-1.14.0/
    RUN ./configure --prefix=/usr/local/nginx --without-http_gzip_module --with-pcre=/usr/local/src/pcre-8.37 && make && make install
    ADD nginx.conf /usr/local/nginx/conf/
    
    
    VOLUME ["/usr/share/nginx/html/webapp/"]
    ENV PATH /usr/local/nginx/sbin:$PATH
    
    EXPOSE 80 8090 8000
    
    ENTRYPOINT ["nginx"]
    

    编译镜像:在nginx_vs文件夹下运行命令

    docker build -t nginx:v1.0 .
    

    运行容器: 运行命令:

    docker run -it --name nginx_test -p 8090:8090 -v /home/user/vs/vsapp/vscode/:/usr/share/nginx/html/webapp nginx:v1.0
    

    4. redis镜像

    redis在该vscode系统中充当的角色是任务队列,故直接制作原始的redis镜像即可。不过为了使我们能在宿主机上查看redis镜像运行容器时产生的数据库数据与log,我们有必要重新配置redis配置文件redis.conf。
    拿到原始的redis.conf修改以下几处:

    # 指定log存放路径
    logfile /data/logs/redis.log
    # 指定数据库存放路径
    dir /data/redisData/
    # 若连接redis需要密码,则配置以下项
    requirepass 1234*
    

    在redis_vs下建立文件夹data,并将修改后的redis.conf放到data中,再在data目录中建立logs、redisData文件夹,logs文件夹中建立名为redis.log的文件。整个redis_vs的目录结构如下:

    -- redis_vs
      -- data
        -- redisData
        -- logs
          -- redis.log
        -- redis.conf
      -- Dockerfile
    

    redis的Dockerfile文件内容如下(我这里安装的redis版本为3.0.6):

    FROM  ubuntu:16.04
    
    RUN apt-get update
    RUN apt-get install gcc -y
    RUN apt-get install g++ -y
    RUN apt-get install make -y
    RUN apt-get install wget -y
    
    RUN 
      cd /tmp && 
      wget http://download.redis.io/releases/redis-3.0.6.tar.gz && 
      tar xvzf redis-3.0.6.tar.gz && 
      cd redis-3.0.6 && 
      make && 
      make install && 
      cp -f src/redis-sentinel /usr/local/bin && 
      mkdir -p /etc/redis && 
      cp -f *.conf /etc/redis && 
      rm -rf /tmp/redis-3.0.6* && 
      sed -i 's/^(bind .*)$/# 1/' /etc/redis/redis.conf && 
      sed -i 's/^(daemonize .*)$/# 1/' /etc/redis/redis.conf && 
      sed -i 's/^(dir .*)$/# 1
    dir /data/' /etc/redis/redis.conf && 
      sed -i 's/^(logfile .*)$/# 1/' /etc/redis/redis.conf
      
    # Define mountable directories.
    VOLUME ["/data"]
    COPY data/redis.conf .
    # Define working directory.
    WORKDIR /data
    # Define default command.
    # CMD ["redis-server", "redis.conf"]
    
    # Expose ports.
    EXPOSE 6379
    

    编译镜像: 在redis_vs目录下运行命令:

    docker build -t redis:v1.0 .
    

    运行容器: 运行如下命令:

    docker run -it --name redis_test -p 6379:6379 -v /home/user/vs/redis_vs/data/:/data/ redis:v1.0
    

    当进入到容器中,在容器中运行命令“redis-server redis.conf”即可启动redis服务。

    5. 编写docker-compose.yml

    现在所有的镜像都已编译成功,下面就是将这些镜像所运行的容器联合起来以搭建成系统。这里我们采用docker-compose对这些镜像进行编排。
    在vsapp下建立名为docker-compose.yml的文件,其内容如下:

    version: '3'
    services:
      mongodb:
        image: mongodb:v1.0
        ports:
          - "27017:27017"
          - "27018:27018"
        volumes:
          - "$PWD/mongodb_vs/data/db/:/data/db"
          - "$PWD/mongodb_vs/data/log/:/data/log/"
        command: ["./start_mongo.sh"]
      webapp:
        image: vsapp:v1.0
        network_mode: "host"
        ports:
          - "8000:8000"
        volumes:
          - "$PWD/vsapp/vscode/:/web/vscode/"
          - "$PWD/vsapp/celerywork.log:/var/log/celery/worker1.log"
        depends_on:
          - mongodb
          - nginx
          - redis
        command: ["./run_web.sh"]
      nginx:
        image: nginx:v1.0
        network_mode: "host"
        ports:
          - "8090:8090"
        volumes:
          - "$PWD/vsapp/vscode/:/usr/share/nginx/html/webapp"
      redis:
        image: redis:v1.0
        network_mode: "host"
        ports:
          - "6379:6379"
        volumes:
          - "$PWD/redis_vs/data/:/data/"
        command: ["redis-server","redis.conf"]
    

    此时,docker-compose已经编写完成,下面就是利用docker-compose运行这些容器了
    运行命令:

    docker-compose up
    

    若运行后没有报错,说明整个系统已经搭建并启动成功。可以对该系统进行访问尝试。

    总结

    将系统进行docker化其实就是重新对原来的系统进行了一个在新机器上的配置,只不过配置的可以分应用一个个配置了。

  • 相关阅读:
    POJ 1981 最大点覆盖问题(极角排序)
    POJ 1286 Pólya定理
    POJ 1830 高斯消元
    HDU 3364 高斯消元
    Educational Codeforces Round 42D. Merge Equals(STL)
    ZOJ 3955:Saddle Point(思维)
    POJ 3301:Texas Trip(计算几何+三分)
    SCUT 125 :笔芯回文(DP)
    ZOJ 3953:Intervals(优先队列+思维)
    Codeforces Gym101097I:Sticks (思维)
  • 原文地址:https://www.cnblogs.com/jack-233/p/11533350.html
Copyright © 2011-2022 走看看