有需求须要对django系统进行docker化,以达到灵活部署和容灾。该系统基于django 2.2版本开发,数据库采用mongodb,服务器使用nginx,因系统有部分异步任务,异步任务则采用clelery+redis实现。
基于该需求,所采用的思路是:“基于ubuntu16.04”源镜像,根据dockerfile制做各个运行环境的镜像。因docker提倡单应用单镜像,故这里将django源代码程序做为一个镜像、mongodb做为一个镜像、nginx做为一个镜像、redis做为一个镜像。并最终使用docker-compose对这些镜像作编排。(假设当前已了解docker与docker-compose知识)html
下面就是一步步制做docker镜像了。关于各个镜像的Dockerfile模板,这里有一个很是好用的网站,可在网站中搜索本身感兴趣的项目,获得其Dockerfile。假设ubuntu16.04的源镜像及版本名为:ubuntu:16.04。
首先咱们在宿主机(宿主机为ubuntu16.04系统,用户为user)中创建一个父文件夹例如名为vs,其中的目录以下:
node
mongodb_vs: 存放mongod的数据、配置文件与dockerfile文件;
vsapp: 存放django系统的源代码、相关配置文件与dockerfile文件;
redis_vs: 存放redis的配置文件与dockerfile文件;
nginx_vs: 存放nginx的配置文件与dockerfile文件。python
首先是mongodb镜像的Dockerfile,内容以下:mysql
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)。总体目录以下:nginx
--mongodb_vs --Dockerfile --mongodb.conf --data --db --log
mongodb.conf内容以下:git
# db path dbpath = /data/db/ # log path logpath = /data/log/logs.log port = 27017 # fork = true # auth = true
以上内容中,fork表示是否在后台运行mongodb,auth表示mongodb是否要进行认证,目前咱们先将这两个禁用掉。
编译镜像:在mongodb_vs文件夹下运行以下命令:github
docker build -t mongodb:v1.0 .
命令运行后如果没有报错,则会编译出一个名为:mongodb:v1.0的镜像。
运行容器:在mongodb文件夹下运行以下命令:web
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实例)。redis
因该系统采用python的django框架完成。故须要系统有python环境。咱们能够先基于ubuntu源镜像制做一个python3的镜像,再基于python3的镜像制做源程序镜像。
制做python3的镜像方法有不少,这里列出一种供参考:
python3.6.3的Dockerfilesql
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的镜像。
下面就是制做源程序的镜像,制做以前还须要一些准备工做:
将源程序代码放入到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;
利用命令“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
因项目中使用了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的配置详情,可参考这篇博客
因源程序中采用的是“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
下面就是配置源程序运行的启动命令。因源程序运行既须要启动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
准备工做作完后,就是编写源程序的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”,便可启动源程序的服务,若期间没有报错,则源程序镜像制做成功。
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
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\ndir \/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服务。
如今全部的镜像都已编译成功,下面就是将这些镜像所运行的容器联合起来以搭建成系统。这里咱们采用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化其实就是从新对原来的系统进行了一个在新机器上的配置,只不过配置的能够分应用一个个配置了。