作者简介:鸿哥,硕士研究生,国内某通信设备公司软件研发工程师,主要从事云计算、SDN技术开发
1、 docker简介
docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、Bare metal、OpenStack 集群和其他的基础应用平台。
2、 docker常用命令解析
1 2 3 4 5 6 7 8 9 10 11 |
docker ps 查看当前正在运行的容器 docker ps -a 查看所有容器的状态 docker start/stop id/name 启动/停止某个容器 docker attach id 进入某个容器(使用exit退出后容器也跟着停止运行) docker exec -ti id 启动一个伪终端以交互式的方式进入某个容器(使用exit退出后容器不停止运行) docker images 查看本地镜像 docker rm id/name 删除某个容器 docker rmi id/name 删除某个镜像 docker run --name test -ti ubuntu /bin/bash 复制ubuntu容器并且重命名为test且运行,然后以伪终端交互式方式进入容器,运行bash docker build -t soar/centos:7.1 . 通过当前目录下的 dockerfile创建一个名为soar/centos:7.1的镜像 docker run -d -p 2222:22 --name test soar/centos:7.1 以镜像soar/centos:7.1创建名为test的容器,并以后台模式运行,并做端口映射到宿主机2222端口,P参数重启容器宿主机端口会发生改变 |
3、 docker实战-需要实现的架构
本文重点讲解如何使用 docker来搭建应用平台,在一台linux服务器上搭建如下结构的应用,其中包括一个HAProxy代理服务器(容器),目的是保证APP(Django)的高可用性,2个Django应用容器,3个Redis内存数据库容器。HAProxy将用户请求转发至另一台Django容器,由Django容器进行逻辑处理,并通过Redis(master)获取内存数据库数据,而Redis(master)与Redis(slave)进行数据同步。
4、实现步骤
1)搭建 docker应用环境
安装 docker软件
1 2 3 4 5 6 7 8 9 |
$sudo apt-get update $sudo apt-get install docker.io 修改镜像源 $sudo vi /etc/default/ docker 添加 DOCKER_OPTS="--registry-mirror=https:// docker.mirrors.ustc.edu.cn" 其他镜像 docker 官方中国区 https://registry. docker-cn.com 网易 http://hub-mirror.c.163.com ustc大学 https:// docker.mirrors.ustc.edu.cn |
启动 docker服务
1 |
$sudo service docker start |
测试下是否可以使用
1 |
$sudo docker run ubuntu:15.10 /bin/echo "Hello world" |
输出
1 2 3 4 5 6 7 8 9 |
Unable to find image 'ubuntu:15.10' locally 15.10: Pulling from library/ubuntu 7dcf5a444392: Pull complete 759aa75f3cee: Pull complete 3fa871dc8a2b: Pull complete 224c42ae46e7: Pull complete Digest: sha256:02521a2d079595241c6793b2044f02eecf294034f31d6e235ac4b2b54ffc41f3 Status: Downloaded newer image for ubuntu:15.10 Hello world |
意思是 docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果,同时 docker首先从本地主机上查找镜像是否存在,如果不存在, docker 就会从镜像仓库 docker Hub 下载公共镜像。
2)获取应用栈各节点所需要的镜像
docker从 docker hub上获取HAProxy、redis、以及Django的镜像。
1 2 3 4 5 |
$sudo docker pull ubuntu $sudo docker pull django $sudo docker pull haproxy $sudo docker pull redis $sudo docker images //显示所有镜像 |
3)配置好各个容器之间的网络通信,由于这里是所有容器都在同一个服务器上,因此可以忽略各个主机之间的连接,只需要配置好各个容器之间的连接即可。使用--link参数能够进行容器间的安全通信,使用格式为name:alias,例如:
1 |
$sudo docker run --link redis:redis --name console ubuntu bash |
表示将在ubuntu镜像上启动一个容器,并启动该容器的bash,同时命名为console,同时将新启动的console容器连接到名为redis容器上。因此应用栈启动命令如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
启动redis $sudo docker run -it --name redis-master redis /bin/bash 打开另外一个tty输入 $sudo docker run -it --name redis-slave1 --link redis-master:master redis /bin/bash 再打开一个tty $sudo docker run -it --name redis-slave2 --link redis-master:master redis /bin/bash 打开一个tty启动django $sudo docker run -it --name APP1 --link redis-master:db -v ~/Projects/Django/App1:/usr/src/app django /bin/bash 打开一个tty $sudo docker run -it --name APP2 --link redis-master:db -v ~/Projects/Django/App2:/usr/src/app django /bin/bash 打开一个tty启动Haproxy容器 $sudo docker run -it --name HAProxy --link APP1:APP1 --link APP2:APP2 -p 6301:6301 -v ~/Projects/HAProxy:/tmp haproxy /bin/bash |
4)节点内部的配置
配置redis主数据库的redis配置,由于容器的轻量化设计,在容器里面缺乏相应的文本编辑工具,所有借用volume来实现文件的编辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
使用 $sudo docker inspect 65cf 来查看容器信息,65cf是该容器的id的前缀,找到 "Mounts": [ { "Type": "volume", "Name": "42a5213973bb5365db0e040515f48c63cdd5514473285723cd6c5ab36eae4967", "Source": "/var/lib/ docker/volumes/42a5213973bb5365db0e040515f48c63cdd5514473285723cd6c5ab36eae4967/_data", "Destination": "/data", "Driver": "local", "Mode": "", "RW": true, "Propagation": "" } ], |
可以看到在主机/var/lib/ docker/volumes/42a5213973bb5365db0e040515f48c63cdd5514473285723cd6c5ab36eae4967/_data映射到了容器的/data目录,因此进入主机的/var/lib/ docker/volumes/42a5213973bb5365db0e040515f48c63cdd5514473285723cd6c5ab36eae4967/_data目录,创建redis.conf文件,在网上找了该文件的内容,填入redis.conf然后修改以下几个参数
daemonize yes
pidfile /var/run/redis.pid
在容器中可以看到该文件,然后将该文件复制到运行环境
cp redis.conf /usr/local/bin/
cd /usr/local/bin/
./redis-server redis.conf
同理在redis slave上也是类似配置,最后在redis slave上的redis.conf
修改参数为
daemonize yes
pidfile /var/run/redis.pid
slaveof master 6379
最后都执行
./redis-server redis.conf
测试是否配置成功,
1 2 3 4 5 6 7 8 9 10 11 12 |
在redis master上启动redis客户端,存储一个数据 redis-cli 127.0.0.1:6379> set master 65cf 127.0.0.1:6379> get master "65cf" 在redis slave上执行redis-cli,获取master的值 root@91961ee165f2:/usr/local/bin# redis-cli 127.0.0.1:6379> get master "65cf" root@da2af08abdeb:/usr/local/bin# redis-cli 127.0.0.1:6379> get master "65cf" |
4)APP容器节点Django的配置
安装python的redis支持包,
1 2 3 4 5 6 7 8 9 |
在app1上执行 pip install redis 并且测试下 python Python 3.4.5 (default, Dec 14 2016, 18:54:20) [GCC 4.9.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import redis >>> print(redis.__file__) /usr/local/lib/python3.4/site-packages/redis/__init__.py |
在容器中创建app
1 2 3 4 5 6 7 |
cd /usr/src/app/ mkdir dockerweb cd dockerweb/ django-admin.py startproject redisweb cd redisweb/ python manage.py startapp helloworld # ls |
helloworld manage.py redisweb
切换至主机的/home/ubuntu/Projects/Django/App1可以看到刚刚创建的那些文件
1 2 3 4 |
cd /home/ubuntu/Projects/Django/App1 ls dockerweb cd /home/ubuntu/Projects/Django/App1/ dockerweb/redisweb/helloworld |
切换至root用户
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$sudo su vi views.py 内容如下 from django.shortcuts import render from django.http import HttpResponse # Create your views here. import redis def hello(request): str=redis.__file__ str+=" " r = redis.Redis(host='db',port=6379,db=0) info=r.info() str+=("Set Hi ") r.set('Hi','Helloworld-APP1') str+=("Get Hi:%s " % r.get(Hi)) str+=("Redis Info: ") str+=("Key:Info:Value") for key in info: str+=("%s:%s " % (key, info[key])) return HttpResponse(str) |
然后修改redisweb项目的配置文件setting.py,将helloworld添加进去。
1 2 3 4 5 6 7 8 9 10 11 |
vi setting.py ALLOWED_HOSTS = ['*'] INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'helloworld', ] |
最后修改redisweb的urls.py,将其设置为访问应用url模式
vi urls.py 内容如下
1 2 3 4 5 6 7 8 |
from django.conf.urls import url from django.contrib import admin from helloworld.views import hello urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^helloworld$', hello), ] |
主机下修改好了之后需要在容器里面执行以下:
1 2 3 |
cd /usr/src/app/ dockerweb/redisweb python manage.py makemigrations python manage.py migrate |
APP2也是类似的配置。
最后一步,启动APP1
1 2 3 4 5 6 7 8 |
python manage.py runserver 0.0.0.0:8001 Performing system checks... System check identified no issues (0 silenced). May 01, 2018 - 07:58:05 Django version 1.10.4, using settings 'redisweb.settings' Starting development server at http://0.0.0.0:8001/ Quit the server with CONTROL-C. |
项目在以下地址:
https://pan.baidu.com/s/11hwF2qMzSZ_EyZenF7mtpg
密码:xuut
5)HAProxy容器节点配置
利用HAProxy进行负载均衡,在主机中,进入HAProxy目录。
vi haproxy.cfg 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
global log 127.0.0.1 local0 maxconn 4096 chroot /usr/local/sbin daemon nbproc 4 pidfile /usr/local/sbin/haproxy.pid defaults log 127.0.0.1 local3 mode http option dontlognull option redispatch retries 2 maxconn 2000 balance roundrobin timeout connect 5000ms timeout client 50000ms timeout server 50000ms listen redis_proxy 0.0.0.0:6301 stats enable stats uri /haproxy-stats server APP1 APP1:8001 check inter 2000 rise 2 fall 5 server APP2 APP2:8002 check inter 2000 rise 2 fall 5 |
然后进入容器中,在/tmp目录下将haproxy.cfg复制到/usr/local/sbin/
cd /tmp/
ls
haproxy.cfg
cp haproxy.cfg /usr/local/sbin/
cd /usr/local/sbin/
ls
haproxy haproxy.cfg
利用该配置文件启动haproxy
./haproxy -f haproxy.cfg
此时可以通过以下链接进行测试
http://172.17.0.7:6301/helloworld
5、总结
通过搭建6个docker容器节点来实验HAProxy、Django、redis组成的服务,本例中采用web返回最简单的Helloworld来模拟常用的web应用,实际部署当中可以将Django换成Tomcat等java应用服务器,并且可以添加关系型数据库来持久化用户数据。从实验可以看出,实验 docker容器搭建起来非常方便灵活,占用资源少等特点。