作者简介:鸿哥,硕士研究生,国内某通信设备公司软件研发工程师,主要从事云计算、SDN技术开发
1、 docker简介
docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、Bare metal、OpenStack 集群和其他的基础应用平台。
2、 docker常用命令解析
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参数重启容器宿主机端口会发生改变
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-tsoar/centos:7.1. 通过当前目录下的 dockerfile创建一个名为soar/centos:7.1的镜像
docker run-d-p2222: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软件
$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
$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服务
$sudo service docker start
$sudo service docker start
测试下是否可以使用
$sudo docker run ubuntu:15.10 /bin/echo "Hello world"
$sudo docker run ubuntu:15.10/bin/echo"Hello world"
输出
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
Unable tofind 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 forubuntu:15.10
Hello world
意思是 docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果,同时 docker首先从本地主机上查找镜像是否存在,如果不存在, docker 就会从镜像仓库 docker Hub 下载公共镜像。
2)获取应用栈各节点所需要的镜像
docker从 docker hub上获取HAProxy、redis、以及Django的镜像。
$sudo docker pull ubuntu
$sudo docker pull django
$sudo docker pull haproxy
$sudo docker pull redis
$sudo docker images //显示所有镜像
$sudo docker pull ubuntu
$sudo docker pull django
$sudo docker pull haproxy
$sudo docker pull redis
$sudo docker images //显示所有镜像
3)配置好各个容器之间的网络通信,由于这里是所有容器都在同一个服务器上,因此可以忽略各个主机之间的连接,只需要配置好各个容器之间的连接即可。使用--link参数能够进行容器间的安全通信,使用格式为name:alias,例如:
$sudo docker run --link redis:redis --name console ubuntu bash
$sudo docker run--link redis:redis--name console ubuntu bash
表示将在ubuntu镜像上启动一个容器,并启动该容器的bash,同时命名为console,同时将新启动的console容器连接到名为redis容器上。因此应用栈启动命令如下:
启动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
启动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-p6301:6301-v~/Projects/HAProxy:/tmp haproxy/bin/bash
4)节点内部的配置
配置redis主数据库的redis配置,由于容器的轻量化设计,在容器里面缺乏相应的文本编辑工具,所有借用volume来实现文件的编辑。
使用 $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": ""
}
],
使用$sudo docker inspect65cf 来查看容器信息,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
测试是否配置成功,
在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"
在redis master上启动redis客户端,存储一个数据
redis-cli
127.0.0.1:6379>set master65cf
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支持包,
在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
在app1上执行
pip install redis 并且测试下
python
Python3.4.5(default,Dec142016,18:54:20)
[GCC4.9.2]on linux
Type"help","copyright","credits"or"license"formore information.
>>>importredis
>>>print(redis.__file__)
/usr/local/lib/python3.4/site-packages/redis/__init__.py
在容器中创建app
cd /usr/src/app/
mkdir dockerweb
cd dockerweb/
django-admin.py startproject redisweb
cd redisweb/
python manage.py startapp helloworld
# ls
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可以看到刚刚创建的那些文件
cd /home/ubuntu/Projects/Django/App1
ls
dockerweb
cd /home/ubuntu/Projects/Django/App1/ dockerweb/redisweb/helloworld
cd/home/ubuntu/Projects/Django/App1
ls
dockerweb
cd/home/ubuntu/Projects/Django/App1/ dockerweb/redisweb/helloworld
切换至root用户
$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+="<br>"
r = redis.Redis(host='db',port=6379,db=0)
info=r.info()
str+=("Set Hi<br>")
r.set('Hi','Helloworld-APP1')
str+=("Get Hi:%s <br>" % r.get(Hi))
str+=("Redis Info:<br>")
str+=("Key:Info:Value")
for key in info:
str+=("%s:%s<br>" % (key, info[key]))
return HttpResponse(str)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$sudo su
vi views.py 内容如下
from django.shortcuts importrender
from django.http importHttpResponse
#Create your views here.
importredis
def hello(request):
str=redis.__file__
str+="<br>"
r=redis.Redis(host='db',port=6379,db=0)
info=r.info()
str+=("Set Hi<br>")
r.set('Hi','Helloworld-APP1')
str+=("Get Hi:%s <br>"%r.get(Hi))
str+=("Redis Info:<br>")
str+=("Key:Info:Value")
forkey ininfo:
str+=("%s:%s<br>"%(key,info[key]))
returnHttpResponse(str)
然后修改redisweb项目的配置文件setting.py,将helloworld添加进去。
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',
]
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 内容如下
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),
]
from django.conf.urls importurl
from django.contrib importadmin
from helloworld.views importhello
urlpatterns=[
url(r'^admin/',admin.site.urls),
url(r'^helloworld$',hello),
]
主机下修改好了之后需要在容器里面执行以下:
cd /usr/src/app/ dockerweb/redisweb
python manage.py makemigrations
python manage.py migrate
cd/usr/src/app/ dockerweb/redisweb
python manage.py makemigrations
python manage.py migrate
APP2也是类似的配置。
最后一步,启动APP1
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.
python manage.py runserver0.0.0.0:8001
Performing system checks...
System check identified no issues(0silenced).
May01,2018-07:58:05
Django version1.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 内容如下:
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
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
log127.0.0.1local0
maxconn4096
chroot/usr/local/sbin
daemon
nbproc4
pidfile/usr/local/sbin/haproxy.pid
defaults
log127.0.0.1local3
mode http
option dontlognull
option redispatch
retries2
maxconn2000
balance roundrobin
timeout connect5000ms
timeout client50000ms
timeout server50000ms
listen redis_proxy0.0.0.0:6301
stats enable
stats uri/haproxy-stats
server APP1 APP1:8001check inter2000rise2fall5
server APP2 APP2:8002check inter2000rise2fall5
然后进入容器中,在/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容器搭建起来非常方便灵活,占用资源少等特点。