本文实例讲述了Docker搭建简单的应用栈与容器Hello World访问。分享给大家供大家参考,具体如下:
这里参考《Docker容器和容器云》 2.3.2章节应用栈搭建过程,对原书中出现的问题 -镜像不断的更新导致- 做了修改,特此说明。
系统环境
操作系统版本
1
2
|
$ cat /etc/issue
Debian GNU /Linux 8 \n \l
|
内核版本
1
2
|
$ uname -r
3.16.0-4-amd64
|
Docker版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
docker version
Client:
Version: 1.12.1
API version: 1.24
Go version: go1.6.3
Git commit: 23cf638
Built: Thu Aug 18 05:02:53 2016
OS /Arch : linux /amd64
Server:
Version: 1.12.1
API version: 1.24
Go version: go1.6.3
Git commit: 23cf638
Built: Thu Aug 18 05:02:53 2016
OS /Arch : linux /amd64
|
应用栈搭建
我们将搭建一个包含6个节点的Docker应用栈,其中包括一个代理节点、两个Web应用节点、一个主数据库节点及两个从数据库节点。应用栈的具体结构如图所示:
获取应用栈节点所需的镜像
根据应用栈结构,需要从Docker Hub获取HAProxy、Redis和Django的镜像:
1
2
3
4
5
6
7
8
9
10
|
# docker pull ubuntu:14.04
# docker pull haproxy
# docker pull redis
# docker pull django
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
haproxy latest 65599e2ea3f2 2 weeks ago 139.1 MB
redis latest 0d1cbfaa41da 2 weeks ago 185 MB
ubuntu 14.04 4a725d3b3b1c 3 weeks ago 188 MB
django latest 79d802ec2b6c 4 weeks ago 437.4 MB
|
应用栈容器节点互联
1
|
docker run --link redis:redis --name console ubuntu bash
|
此处将在Ubuntu镜像上启动一个容器,并命名为console,同时将新启动的console容器连接到名为redis的容器上。docker run 命令的 --link选项用于添加连接到一个容器。这里还使用了 --name选项为容器指定名称。
关于Docker link用法可参考本站《Docker如何使用link建立容器之间的连接》
应用栈节点启动
启动应用栈节点之前先整理应用栈节点的连接过程:
- 启动redis-master容器节点;
- 两个redis-slave容器节点启动时连接到redis-master;
- 两个APP容器节点启动时连接到redis-master;
- HAProxy容器节点启动时连接到两个APP节点。
此外,为了能够从外网访问应用栈,并通过HAproxy节点访问应用栈中的APP,在启动HAProxy节点时使用-p参数将端口暴露给主机。
综上,容器启动顺序为:
redis-master -》redis slave -》APP -》HAProxy
启动Redis容器
1
2
3
|
# docker run -it --name redis-master redis /bin/bash
# docker run -it --name redis-slave1 --link redis-master:master redis /bin/bash
# docker run -it --name redis-slave2 --link redis-master:master redis /bin/bash
|
启动Django容器
1
2
|
# docker run -it --name APP1 --link redis-master:db -v ~/Projects/Django/APP1:/usr/src/app django /bin/bash
# docker run -it --name APP2 --link redis-master:db -v ~/Projects/Django/APP2:/usr/src/app django /bin/bash
|
启动HAproxy容器
1
|
# docker run -it --name HAProxy --link APP1:APP1 --link APP2:APP2 -p 6301:6301 -v ~/Projects/HAProxy:tmp haproxy /bin/bash
|
说明:启动每个容器时都需分配一个终端。
容器启动信息查看:
1
2
3
4
5
6
7
8
|
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ab25650701f0 haproxy "/docker-entrypoint.s" 3 hours ago Up 3 hours 0.0.0.0:6301->6301 /tcp HAProxy
ace790044e06 django "/bin/bash" 3 hours ago Up 3 hours APP2
64963af16131 django "/bin/bash" 3 hours ago Up 3 hours APP1
aa77330aee2a redis "docker-entrypoint.sh" 3 hours ago Up 3 hours 6379 /tcp redis-slave2
1fd72289d4f2 redis "docker-entrypoint.sh" 3 hours ago Up 3 hours 6379 /tcp redis-slave1
518b41200dab redis "docker-entrypoint.sh" 3 hours ago Up 3 hours 6379 /tcp redis-master
|
应用栈容器节点配置
Redis Master主数据库容器节点配置
我们知道通过volume可以在宿主机和容器之间共享数据,因此可在宿主机上创建和编辑Redis的启动配置文件。使用docker inpect命令查看volume挂载情况:
1
2
|
# docker inspect -f '{{ .Mounts }}' redis-master
[{5920a23b5e230a449230bbd4807912793bbc3bab0a05ae085ff95423301f0d6c /var/lib/docker/volumes/5920a23b5e230a449230bbd4807912793bbc3bab0a05ae085ff95423301f0d6c/_data /data local true }]
|
可以看出,redis-master的volume在宿主机上为目录/var/lib/docker/volumes/5920a23b5e230a449230bbd4807912793bbc3bab0a05ae085ff95423301f0d6c/_data,在容器中为/data。
执行如下命令创建Redis的启动配置文件redis.conf:
1
2
3
|
# cd /var/lib/docker/volumes/5920a23b5e230a449230bbd4807912793bbc3bab0a05ae085ff95423301f0d6c/_data
# cp /~/redis.conf .
# vim redis.conf
|
对于redis主数据库,修改如下模板文件中的几个参数:
1
2
|
daemonize yes
pidfile /var/run/redis .pid
|
redis.conf模板下载:https://github.com/yhsong-linux/docker-redis/blob/master/redis.conf
在宿主机上创建好启动配置文件后,切换到容器中的/data目录,将redis.conf拷贝到执行工作目录,然后启动redis服务:
1
2
3
4
|
# cd /data
# cp redis.conf /usr/local/bin
# cd /usr/local/bin
# redis-server redis.conf
|
Redis Slave从数据库容器节点配置
与Redis Master容器节点类似,在启动Redis Slave容器节点之后,需要查看vloume信息,并创建启动配置文件。
对于Redis从数据库,需要修改如下几个参数:
1
2
3
|
daemonize yes
pidfile /var/run/redis .pid
slaveof master 6379
|
在宿主机上创建好启动配置文件后,切换到容器中的/data目录,将redis.conf拷贝到执行工作目录,然后启动redis服务:
1
2
3
4
|
# cd /data
# cp redis.conf /usr/local/bin
# cd /usr/local/bin
# redis-server redis.conf
|
Redis数据库容器节点测试
在Redis Master和Redis Slave容器节点的配置和服务启动后,可以通过启动Redis的客户端程序来测试数据库。
首先,在Redis Master容器内,启动Redis的客户端程,并存储一个数据:
1
2
3
4
5
|
# redis-cli
127.0.0.1:6379> set master 518b
OK
127.0.0.1:6379> get master
"518b"
|
接着,在两个Redis Slave容器内,分别启动Redis的客户端程,查询之前在Master数据库中存储的数据:
1
2
3
|
# redis-cli
127.0.0.1:6379> get master
"518b"
|
根据响应可知,Master数据库中的数据已经同步到Slave数据库中。至此,应用栈的数据库部分搭建完成。
APP容器节点(Django)的配置
Django容器启动后,需要利用Django框架,开发一个简单的Web程序。为了访问数据库,需要在容器中安装Python的Redis支持包:
1
|
# pip install redis
|
安装完成后,验证支持包是否安装成功:
1
2
3
4
5
6
7
|
# python
Python 3.4 . 5 (default, Aug 22 2016 , 20 : 55 : 07 )
[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
|
如上面的输出,则表示现在可以使用Pythob语言调用Redis数据库了。接下来创建Web程序。以APP1为例,进入宿主机的volume目录对新建APP进行编辑。
在容器的volume目录下/usr/src/app下,开始创建APP:
1
2
3
4
5
6
7
8
9
10
11
12
|
# cd /usr/src/app
# mkdir dockerweb
# cd dockerweb
# django-admin.py startproject redisweb
# ls
redisweb
# cd redisweb
# ls
manage.py redisweb
# python manager.py startapp helloworld
# ls
helloworld manage.py redisweb
|
在容器中创建APP后,切换到宿主机的volume目录~/Projects/Django/App1下:
1
2
3
|
# cd ~/Projects/Django/App1
# ls
dockerweb
|
可以看到,在容器内创建的APP文件在宿主机的volume目录下同样可见。然后修改helloword应用的视图文件views.py:
1
2
3
4
|
# cd dockerweb/redisweb/helloworld
# ls
admin.py __init__.py migrations models.py tests.py views.py
# vim views.py
|
修改后的views.py文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
import redis
def hello(requset):
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 )
|
注意,连接Redis数据库时,使用–link参数创建db连接来代替具体的IP地址;同理,对于APP2,使用想要的db连接即可。
接下来,修改redisweb项目的配置文件setiing.py,添加新建的helloworld应用:
1
2
3
|
# cd ../redisweb
# ls
__init__.py __pycache__ settings.py urls.py wsgi.py
|
在setting.py文件中的INSTALLED_APPS选项下添加helloworld:
1
2
3
4
5
6
7
8
9
10
|
# Application definition
INSTALLED_APPS = [
'django.contrib.admin' ,
'django.contrib.auth' ,
'django.contrib.contenttypes' ,
'django.contrib.sessions' ,
'django.contrib.messages' ,
'django.contrib.staticfiles' ,
'helloworld' ,
]
|
最后,修改redisweb项目的URL模板文件urls.py,它将设置访问应用的URL模式,并为URL模式调用的视图函数之间的映射表:
1
|
# vim urls.py
|
在url.py文件中,引入helloworld应用的hello视图,并为hello视图添加一个urlpatterns变量。修改后的urls.py文件如下:
1
2
3
4
5
6
7
8
|
from django.conf.urls import *
from django.contrib import admin
admin.autodiscover()
from helloworld.views import hello
urlpatterns = [
url(r '^admin/' , include(admin.site.urls)),
url(r '^helloworld$' , hello),
]
|
以上修改完成后,再次进入容器,在目录/usr/src/app/dockerweb/redisweb下生成项目:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# python manage.py makemigrations
No changes detected
# python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Rendering model states... DONE
Applying contenttypes. 0001_initial ... OK
Applying auth. 0001_initial ... OK
Applying admin. 0001_initial ... OK
Applying admin. 0002_logentry_remove_auto_add ... OK
Applying contenttypes. 0002_remove_content_type_name ... OK
Applying auth. 0002_alter_permission_name_max_length ... OK
Applying auth. 0003_alter_user_email_max_length ... OK
Applying auth. 0004_alter_user_username_opts ... OK
Applying auth. 0005_alter_user_last_login_null ... OK
Applying auth. 0006_require_contenttypes_0002 ... OK
Applying auth. 0007_alter_validators_add_error_messages ... OK
Applying auth. 0008_alter_user_username_max_length ... OK
Applying sessions. 0001_initial ... OK
|
至此,所有APP1容器的配置已经完成,APP2容器的配置也是同样的过程。配置完成APP1和APP2的容器后,就完成了应用栈的APP部分的全部配置。
在启动APP容器的Web服务器时,可以指定服务器的端口和IP地址,为了通过HAproxy容器节点接受外网所有的公共IP地址访问,实现负载均衡,需要指定服务器的IP地址和端口。对于APP1使用8001端口,而APP2使用8002端口,同时,都使用0.0.0.0地址。以APP1为例,启动服务器的过程如下:
1
2
3
4
5
6
7
8
9
|
# python manage.py runserver 0.0.0.0:8001
# python manage.py runserver 0.0.0.0:8001
Performing system checks...
System check identified no issues ( 0 silenced).
September 20 , 2016 - 23 : 16 : 44
Django version 1.10 , using settings 'redisweb.settings'
Starting development server at http: / / 0.0 . 0.0 : 8001 /
Quit the server with CONTROL - C.
|
HAproxy容器节点配置
所有对应用栈的访问均通过HAproxy负载均衡代理容器节点实现负载均衡。
首先,将HAProxy的启动配置我呢间复制到容器中,在宿主机的volumes目录~/Projects/HAProxy/下:
1
2
|
# cd ~/Projects/HAProxy/
# vim haproxy.cfg
|
修改后的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
bind 0.0.0.0:6301
stats enable
stats uri /haproxy-stats
stats auth phil:NRG93012
server APP1 APP1:8001 check inter 2000 rise 2 fall 5
server APP2 APP2:8002 check inter 2000 rise 2 fall 5
|
随后,进入容器的volume目录/tmp下,将Haproxy的启动配置文件复制到HAproxy的工作目录:
1
2
3
4
5
|
# cd /tmp
# cp haproxy.cfg /usr/local/sbin
# cd /usr/local/sbin
# ls
haproxy haproxy-systemd-wrapper haproxy.cfg
|
然后,利用配置文件启动HAProxy代理:
1
|
# haproxy -f haproxy.cfg
|
应用栈访问测试
在浏览器中访问http://172.17.0.7:6301/helloworld,可以看到APP1或APP2的页面(本地主机访问应用栈):
说明:172.17.0.7是HAProxy容器的地址。
本地测试通过后,尝试在其他主机上通过应用栈入口地址的IP地址和6301端口访问应用栈APP,即http://192.168.1.104:6301/helloworld,如下图所示(外网其他主机访问应用栈):
说明:192.168.1.104是宿主机的IP地址。
希望本文所述对大家docker容器使用有所帮助。
原文链接:https://blog.csdn.net/u012066426/article/details/52597991