Merge pull request #291 from khs1994/master
commit
e6291d57f9
|
@ -10,8 +10,9 @@
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"-livereload",
|
"-livereload",
|
||||||
"image-captions",
|
"image-captions",
|
||||||
"github-buttons",
|
"github",
|
||||||
"page-treeview"
|
"page-treeview",
|
||||||
|
"editlink"
|
||||||
],
|
],
|
||||||
"pluginsConfig": {
|
"pluginsConfig": {
|
||||||
"image-captions": {
|
"image-captions": {
|
||||||
|
@ -20,13 +21,12 @@
|
||||||
},
|
},
|
||||||
"caption": "图 _PAGE_LEVEL_._PAGE_IMAGE_NUMBER_ - _CAPTION_"
|
"caption": "图 _PAGE_LEVEL_._PAGE_IMAGE_NUMBER_ - _CAPTION_"
|
||||||
},
|
},
|
||||||
"github-buttons": {
|
"github": {
|
||||||
"buttons": [{
|
"url": "https://github.com/yeasy/docker_practice"
|
||||||
"user": "yeasy",
|
},
|
||||||
"repo": "docker_practice",
|
"editlink": {
|
||||||
"type": "star",
|
"base": "https://github.com/yeasy/docker_practice/blob/master/",
|
||||||
"size": "small"
|
"label": "编辑本页"
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"page-treeview": {
|
"page-treeview": {
|
||||||
"copyright": "Copyright © yeasy",
|
"copyright": "Copyright © yeasy",
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
|
|
||||||
* 0.9-rc3: 2017-12-20
|
* 0.9-rc3: 2017-12-20
|
||||||
|
|
||||||
|
* 精简示例代码
|
||||||
|
|
||||||
|
* 调整目录结构
|
||||||
|
|
||||||
* 0.9-rc2: 2017-12-10
|
* 0.9-rc2: 2017-12-10
|
||||||
|
|
||||||
* 增加 Docker 中文资源链接
|
* 增加 Docker 中文资源链接
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
[![](https://img.shields.io/github/stars/yeasy/docker_practice.svg?style=social&label=Stars)](https://github.com/yeasy/docker_practice) [![](https://img.shields.io/docker/pulls/yeasy/docker_practice.svg)](https://store.docker.com/community/images/yeasy/docker_practice) [![](https://travis-ci.org/yeasy/docker_practice.svg?branch=master)](https://travis-ci.org/yeasy/docker_practice) [![](https://img.shields.io/github/release/yeasy/docker_practice/all.svg)](https://github.com/yeasy/docker_practice/releases) [![](https://badges.gitter.im/docker_practice/Lobby.svg)](https://gitter.im/docker_practice/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[![](https://img.shields.io/github/stars/yeasy/docker_practice.svg?style=social&label=Stars)](https://github.com/yeasy/docker_practice) [![](https://img.shields.io/docker/pulls/yeasy/docker_practice.svg)](https://store.docker.com/community/images/yeasy/docker_practice) [![](https://travis-ci.org/yeasy/docker_practice.svg?branch=master)](https://travis-ci.org/yeasy/docker_practice) [![](https://img.shields.io/github/release/yeasy/docker_practice/all.svg)](https://github.com/yeasy/docker_practice/releases) [![](https://badges.gitter.im/docker_practice/Lobby.svg)](https://gitter.im/docker_practice/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
0.9-rc1(2017-11-29)
|
0.9-rc2(2017-12-09)
|
||||||
|
|
||||||
*修订说明:本书内容将基于 Docker CE v17.x 进行重新修订,计划 2017 年底发布 0.9.0 版本。旧版本(Docker 1.13-)内容,请阅读 [docker-legacy](https://github.com/yeasy/docker_practice/tree/docker-legacy) 分支的内容。*
|
*修订说明:本书内容将基于 Docker CE v17.MM 进行重新修订,计划 2017 年底发布 0.9.0 版本。旧版本(Docker 1.13-)内容,请阅读 [docker-legacy](https://github.com/yeasy/docker_practice/tree/docker-legacy) 分支的内容。*
|
||||||
|
|
||||||
[Docker](http://www.docker.com) 是个划时代的开源项目,它彻底释放了计算虚拟化的威力,极大提高了应用的运行效率,降低了云计算资源供应的成本!使用 Docker,可以让应用的部署、测试和分发都变得前所未有的高效和轻松!
|
[Docker](http://www.docker.com) 是个划时代的开源项目,它彻底释放了计算虚拟化的威力,极大提高了应用的运行效率,降低了云计算资源供应的成本!使用 Docker,可以让应用的部署、测试和分发都变得前所未有的高效和轻松!
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
* pdf 版本 [下载](https://www.gitbook.com/download/pdf/book/yeasy/docker_practice)
|
* pdf 版本 [下载](https://www.gitbook.com/download/pdf/book/yeasy/docker_practice)
|
||||||
* epub 版本 [下载](https://www.gitbook.com/download/epub/book/yeasy/docker_practice)
|
* epub 版本 [下载](https://www.gitbook.com/download/epub/book/yeasy/docker_practice)
|
||||||
|
|
||||||
Docker 自身仍在快速发展中,生态环境也在蓬勃成长。建议初学者使用最新版的 Docker (v17.x) 进行学习实践。欢迎 [参与维护项目](CONTRIBUTING.md)。
|
Docker 自身仍在快速发展中,生态环境也在蓬勃成长。建议初学者使用最新版的 Docker (v17.MM) 进行学习实践。欢迎 [参与维护项目](CONTRIBUTING.md)。
|
||||||
|
|
||||||
* [修订记录](CHANGELOG.md)
|
* [修订记录](CHANGELOG.md)
|
||||||
* [贡献者名单](https://github.com/yeasy/docker_practice/graphs/contributors)
|
* [贡献者名单](https://github.com/yeasy/docker_practice/graphs/contributors)
|
||||||
|
|
|
@ -57,9 +57,9 @@
|
||||||
* [使用网络](network/README.md)
|
* [使用网络](network/README.md)
|
||||||
* [外部访问容器](network/port_mapping.md)
|
* [外部访问容器](network/port_mapping.md)
|
||||||
* [容器互联](network/linking.md)
|
* [容器互联](network/linking.md)
|
||||||
|
* [配置 DNS](network/dns.md)
|
||||||
* [高级网络配置](advanced_network/README.md)
|
* [高级网络配置](advanced_network/README.md)
|
||||||
* [快速配置指南](advanced_network/quick_guide.md)
|
* [快速配置指南](advanced_network/quick_guide.md)
|
||||||
* [配置 DNS](advanced_network/dns.md)
|
|
||||||
* [容器访问控制](advanced_network/access_control.md)
|
* [容器访问控制](advanced_network/access_control.md)
|
||||||
* [端口映射实现](advanced_network/port_mapping.md)
|
* [端口映射实现](advanced_network/port_mapping.md)
|
||||||
* [配置 docker0 网桥](advanced_network/docker0.md)
|
* [配置 docker0 网桥](advanced_network/docker0.md)
|
||||||
|
|
18
book.json
18
book.json
|
@ -10,8 +10,9 @@
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"-livereload",
|
"-livereload",
|
||||||
"image-captions",
|
"image-captions",
|
||||||
"github-buttons",
|
"github",
|
||||||
"page-treeview"
|
"page-treeview",
|
||||||
|
"editlink"
|
||||||
],
|
],
|
||||||
"pluginsConfig": {
|
"pluginsConfig": {
|
||||||
"image-captions": {
|
"image-captions": {
|
||||||
|
@ -20,13 +21,12 @@
|
||||||
},
|
},
|
||||||
"caption": "图 _PAGE_LEVEL_._PAGE_IMAGE_NUMBER_ - _CAPTION_"
|
"caption": "图 _PAGE_LEVEL_._PAGE_IMAGE_NUMBER_ - _CAPTION_"
|
||||||
},
|
},
|
||||||
"github-buttons": {
|
"github": {
|
||||||
"buttons": [{
|
"url": "https://github.com/yeasy/docker_practice"
|
||||||
"user": "yeasy",
|
},
|
||||||
"repo": "docker_practice",
|
"editlink": {
|
||||||
"type": "star",
|
"base": "https://github.com/yeasy/docker_practice/blob/master/",
|
||||||
"size": "small"
|
"label": "编辑本页"
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"page-treeview": {
|
"page-treeview": {
|
||||||
"copyright": "Copyright © yeasy",
|
"copyright": "Copyright © yeasy",
|
||||||
|
|
|
@ -8,3 +8,4 @@
|
||||||
|
|
||||||
阿里云容器服务提供了高性能、可伸缩的容器应用管理服务,支持在一组云服务器上通过 Docker 容器来进行应用生命周期管理。容器服务极大简化了用户对容器管理集群的搭建工作,无缝整合了阿里云虚拟化、存储、网络和安全能力。容器服务提供了多种应用发布方式和流水线般的持续交付能力,原生支持微服务架构,助力用户无缝上云和跨云管理。
|
阿里云容器服务提供了高性能、可伸缩的容器应用管理服务,支持在一组云服务器上通过 Docker 容器来进行应用生命周期管理。容器服务极大简化了用户对容器管理集群的搭建工作,无缝整合了阿里云虚拟化、存储、网络和安全能力。容器服务提供了多种应用发布方式和流水线般的持续交付能力,原生支持微服务架构,助力用户无缝上云和跨云管理。
|
||||||
|
|
||||||
|
![](https://img.alicdn.com/tps/TB10yjtPpXXXXacXXXXXXXXXXXX-1531-1140.png)
|
||||||
|
|
|
@ -7,3 +7,5 @@
|
||||||
具体包括云服务器、云存储、云数据库和弹性 web 引擎等基础云服务;腾讯云分析(MTA)、腾讯云推送(信鸽)等腾讯整体大数据能力;以及 QQ互联、QQ 空间、微云、微社区等云端链接社交体系。这些正是腾讯云可以提供给这个行业的差异化优势,造就了可支持各种互联网使用场景的高品质的腾讯云技术平台。
|
具体包括云服务器、云存储、云数据库和弹性 web 引擎等基础云服务;腾讯云分析(MTA)、腾讯云推送(信鸽)等腾讯整体大数据能力;以及 QQ互联、QQ 空间、微云、微社区等云端链接社交体系。这些正是腾讯云可以提供给这个行业的差异化优势,造就了可支持各种互联网使用场景的高品质的腾讯云技术平台。
|
||||||
|
|
||||||
腾讯云容器服务是高度可扩展的高性能容器管理服务,用户可以在托管的云服务器实例集群上轻松运行应用程序。使用该服务,将无需安装、运维、扩展用户的集群管理基础设施,只需进行简单的API调用,便可启动和停止Docker应用程序,查询集群的完整状态,以及使用各种云服务。用户可以根据用户的资源需求和可用性要求在用户的集群中安排容器的置放,满足业务或应用程序的特定要求。
|
腾讯云容器服务是高度可扩展的高性能容器管理服务,用户可以在托管的云服务器实例集群上轻松运行应用程序。使用该服务,将无需安装、运维、扩展用户的集群管理基础设施,只需进行简单的API调用,便可启动和停止Docker应用程序,查询集群的完整状态,以及使用各种云服务。用户可以根据用户的资源需求和可用性要求在用户的集群中安排容器的置放,满足业务或应用程序的特定要求。
|
||||||
|
|
||||||
|
![](https://mc.qcloudimg.com/static/img/0581dbeb97c869bbe6e62025dbc592d7/image.png)
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,5 @@
|
||||||
|
FROM python:3.6-alpine
|
||||||
|
ADD . /code
|
||||||
|
WORKDIR /code
|
||||||
|
RUN pip install redis flask
|
||||||
|
CMD ["python", "app.py"]
|
|
@ -0,0 +1,13 @@
|
||||||
|
from flask import Flask
|
||||||
|
from redis import Redis
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
redis = Redis(host='redis', port=6379)
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def hello():
|
||||||
|
count = redis.incr('hits')
|
||||||
|
return 'Hello World! 该页面已被访问 {} 次。\n'.format(count)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(host="0.0.0.0", debug=True)
|
|
@ -0,0 +1,10 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: "redis:alpine"
|
|
@ -1,29 +0,0 @@
|
||||||
version: "3"
|
|
||||||
services:
|
|
||||||
|
|
||||||
weba:
|
|
||||||
build: ./web
|
|
||||||
expose:
|
|
||||||
- 80
|
|
||||||
|
|
||||||
webb:
|
|
||||||
build: ./web
|
|
||||||
expose:
|
|
||||||
- 80
|
|
||||||
|
|
||||||
webc:
|
|
||||||
build: ./web
|
|
||||||
expose:
|
|
||||||
- 80
|
|
||||||
|
|
||||||
haproxy:
|
|
||||||
image: haproxy:latest
|
|
||||||
volumes:
|
|
||||||
- ./haproxy:/haproxy-override
|
|
||||||
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "70:70"
|
|
||||||
expose:
|
|
||||||
- "80"
|
|
||||||
- "70"
|
|
|
@ -1,32 +0,0 @@
|
||||||
global
|
|
||||||
log 127.0.0.1 local0
|
|
||||||
log 127.0.0.1 local1 notice
|
|
||||||
|
|
||||||
defaults
|
|
||||||
log global
|
|
||||||
mode http
|
|
||||||
option httplog
|
|
||||||
option dontlognull
|
|
||||||
timeout connect 5000ms
|
|
||||||
timeout client 50000ms
|
|
||||||
timeout server 50000ms
|
|
||||||
|
|
||||||
listen stats
|
|
||||||
bind 0.0.0.0:70
|
|
||||||
stats enable
|
|
||||||
stats uri /
|
|
||||||
|
|
||||||
frontend balancer
|
|
||||||
bind 0.0.0.0:80
|
|
||||||
mode http
|
|
||||||
default_backend web_backends
|
|
||||||
|
|
||||||
backend web_backends
|
|
||||||
mode http
|
|
||||||
option forwardfor
|
|
||||||
balance roundrobin
|
|
||||||
server weba weba:80 check
|
|
||||||
server webb webb:80 check
|
|
||||||
server webc webc:80 check
|
|
||||||
option httpchk GET /
|
|
||||||
http-check expect status 200
|
|
|
@ -1,5 +0,0 @@
|
||||||
FROM python:2.7
|
|
||||||
WORKDIR /code
|
|
||||||
ADD . /code
|
|
||||||
EXPOSE 80
|
|
||||||
CMD python index.py
|
|
|
@ -1,68 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
#authors: yeasy.github.com
|
|
||||||
#date: 2013-07-05
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import BaseHTTPServer
|
|
||||||
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
|
||||||
import socket
|
|
||||||
import fcntl
|
|
||||||
import struct
|
|
||||||
import pickle
|
|
||||||
from datetime import datetime
|
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
class HandlerClass(SimpleHTTPRequestHandler):
|
|
||||||
def get_ip_address(self,ifname):
|
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
||||||
return socket.inet_ntoa(fcntl.ioctl(
|
|
||||||
s.fileno(),
|
|
||||||
0x8915, # SIOCGIFADDR
|
|
||||||
struct.pack('256s', ifname[:15])
|
|
||||||
)[20:24])
|
|
||||||
def log_message(self, format, *args):
|
|
||||||
if len(args) < 3 or "200" not in args[1]:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
request = pickle.load(open("pickle_data.txt","r"))
|
|
||||||
except:
|
|
||||||
request=OrderedDict()
|
|
||||||
time_now = datetime.now()
|
|
||||||
ts = time_now.strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
server = self.get_ip_address('eth0')
|
|
||||||
host=self.address_string()
|
|
||||||
addr_pair = (host,server)
|
|
||||||
if addr_pair not in request:
|
|
||||||
request[addr_pair]=[1,ts]
|
|
||||||
else:
|
|
||||||
num = request[addr_pair][0]+1
|
|
||||||
del request[addr_pair]
|
|
||||||
request[addr_pair]=[num,ts]
|
|
||||||
file=open("index.html", "w")
|
|
||||||
file.write("<!DOCTYPE html> <html> <body><center><h1><font color=\"blue\" face=\"Georgia, Arial\" size=8><em>HA</em></font> Webpage Visit Results</h1></center>")
|
|
||||||
for pair in request:
|
|
||||||
if pair[0] == host:
|
|
||||||
guest = "LOCAL: "+pair[0]
|
|
||||||
else:
|
|
||||||
guest = pair[0]
|
|
||||||
if (time_now-datetime.strptime(request[pair][1],'%Y-%m-%d %H:%M:%S')).seconds < 3:
|
|
||||||
file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +": <font color=\"red\">"+str(request[pair][0])+ "</font> requests " + "from <<font color=\"blue\">"+guest+"</font>> to WebServer <<font color=\"blue\">"+pair[1]+"</font>></p>")
|
|
||||||
else:
|
|
||||||
file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +": <font color=\"maroon\">"+str(request[pair][0])+ "</font> requests " + "from <<font color=\"navy\">"+guest+"</font>> to WebServer <<font color=\"navy\">"+pair[1]+"</font>></p>")
|
|
||||||
file.write("</body> </html>")
|
|
||||||
file.close()
|
|
||||||
pickle.dump(request,open("pickle_data.txt","w"))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
try:
|
|
||||||
ServerClass = BaseHTTPServer.HTTPServer
|
|
||||||
Protocol = "HTTP/1.0"
|
|
||||||
addr = len(sys.argv) < 2 and "0.0.0.0" or sys.argv[1]
|
|
||||||
port = len(sys.argv) < 3 and 80 or int(sys.argv[2])
|
|
||||||
HandlerClass.protocol_version = Protocol
|
|
||||||
httpd = ServerClass((addr, port), HandlerClass)
|
|
||||||
sa = httpd.socket.getsockname()
|
|
||||||
print "Serving HTTP on", sa[0], "port", sa[1], "..."
|
|
||||||
httpd.serve_forever()
|
|
||||||
except:
|
|
||||||
exit()
|
|
|
@ -1,7 +1,5 @@
|
||||||
## Compose 简介
|
## Compose 简介
|
||||||
|
|
||||||
![Docker Compose 项目](_images/docker_compose.jpg)
|
|
||||||
|
|
||||||
`Compose` 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。从功能上看,跟 `OpenStack` 中的 `Heat` 十分类似。
|
`Compose` 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。从功能上看,跟 `OpenStack` 中的 `Heat` 十分类似。
|
||||||
|
|
||||||
其代码目前在 [https://github.com/docker/compose](https://github.com/docker/compose) 上开源。
|
其代码目前在 [https://github.com/docker/compose](https://github.com/docker/compose) 上开源。
|
||||||
|
|
198
compose/usage.md
198
compose/usage.md
|
@ -1,6 +1,7 @@
|
||||||
## 使用
|
## 使用
|
||||||
|
|
||||||
### 术语
|
### 术语
|
||||||
|
|
||||||
首先介绍几个术语。
|
首先介绍几个术语。
|
||||||
|
|
||||||
* 服务 (`service`):一个应用容器,实际上可以运行多个相同镜像的实例。
|
* 服务 (`service`):一个应用容器,实际上可以运行多个相同镜像的实例。
|
||||||
|
@ -10,197 +11,64 @@
|
||||||
可见,一个项目可以由多个服务(容器)关联而成,`Compose` 面向项目进行管理。
|
可见,一个项目可以由多个服务(容器)关联而成,`Compose` 面向项目进行管理。
|
||||||
|
|
||||||
### 场景
|
### 场景
|
||||||
下面,我们创建一个经典的 Web 项目:一个 [Haproxy](http://www.haproxy.org/),挂载三个 Web 容器。
|
|
||||||
|
|
||||||
创建一个 `compose-haproxy-web` 目录,作为项目工作目录,并在其中分别创建两个子目录:`haproxy` 和 `web`。
|
最常见的项目是 web 网站,该项目应该包含 web 应用和缓存。
|
||||||
|
|
||||||
### web 子目录
|
下面我们用 `Python` 来建立一个能够记录页面访问次数的 web 网站。
|
||||||
|
|
||||||
这里用 Python 程序来提供一个简单的 HTTP 服务,打印出访问者的 IP 和 实际的本地 IP。
|
#### web 应用
|
||||||
|
|
||||||
#### index.py
|
新建文件夹,在该目录中编写 `app.py` 文件
|
||||||
|
|
||||||
编写一个 `index.py` 作为服务器文件,代码为
|
|
||||||
```python
|
```python
|
||||||
#!/usr/bin/python
|
from flask import Flask
|
||||||
#authors: yeasy.github.com
|
from redis import Redis
|
||||||
#date: 2013-07-05
|
|
||||||
|
|
||||||
import sys
|
app = Flask(__name__)
|
||||||
import BaseHTTPServer
|
redis = Redis(host='redis', port=6379)
|
||||||
from SimpleHTTPServer import SimpleHTTPRequestHandler
|
|
||||||
import socket
|
|
||||||
import fcntl
|
|
||||||
import struct
|
|
||||||
import pickle
|
|
||||||
from datetime import datetime
|
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
class HandlerClass(SimpleHTTPRequestHandler):
|
@app.route('/')
|
||||||
def get_ip_address(self,ifname):
|
def hello():
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
count = redis.incr('hits')
|
||||||
return socket.inet_ntoa(fcntl.ioctl(
|
return 'Hello World! 该页面已被访问 {} 次。\n'.format(count)
|
||||||
s.fileno(),
|
|
||||||
0x8915, # SIOCGIFADDR
|
|
||||||
struct.pack('256s', ifname[:15])
|
|
||||||
)[20:24])
|
|
||||||
def log_message(self, format, *args):
|
|
||||||
if len(args) < 3 or "200" not in args[1]:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
request = pickle.load(open("pickle_data.txt","r"))
|
|
||||||
except:
|
|
||||||
request=OrderedDict()
|
|
||||||
time_now = datetime.now()
|
|
||||||
ts = time_now.strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
server = self.get_ip_address('eth0')
|
|
||||||
host=self.address_string()
|
|
||||||
addr_pair = (host,server)
|
|
||||||
if addr_pair not in request:
|
|
||||||
request[addr_pair]=[1,ts]
|
|
||||||
else:
|
|
||||||
num = request[addr_pair][0]+1
|
|
||||||
del request[addr_pair]
|
|
||||||
request[addr_pair]=[num,ts]
|
|
||||||
file=open("index.html", "w")
|
|
||||||
file.write("<!DOCTYPE html> <html> <body><center><h1><font color=\"blue\" face=\"Georgia, Arial\" size=8><em>HA</em></font> Webpage Visit Results</h1></center>")
|
|
||||||
for pair in request:
|
|
||||||
if pair[0] == host:
|
|
||||||
guest = "LOCAL: "+pair[0]
|
|
||||||
else:
|
|
||||||
guest = pair[0]
|
|
||||||
if (time_now-datetime.strptime(request[pair][1],'%Y-%m-%d %H:%M:%S')).seconds < 3:
|
|
||||||
file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +": <font color=\"red\">"+str(request[pair][0])+ "</font> requests " + "from <<font color=\"blue\">"+guest+"</font>> to WebServer <<font color=\"blue\">"+pair[1]+"</font>></p>")
|
|
||||||
else:
|
|
||||||
file.write("<p style=\"font-size:150%\" >#"+ str(request[pair][1]) +": <font color=\"maroon\">"+str(request[pair][0])+ "</font> requests " + "from <<font color=\"navy\">"+guest+"</font>> to WebServer <<font color=\"navy\">"+pair[1]+"</font>></p>")
|
|
||||||
file.write("</body> </html>")
|
|
||||||
file.close()
|
|
||||||
pickle.dump(request,open("pickle_data.txt","w"))
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == "__main__":
|
||||||
try:
|
app.run(host="0.0.0.0", debug=True)
|
||||||
ServerClass = BaseHTTPServer.HTTPServer
|
|
||||||
Protocol = "HTTP/1.0"
|
|
||||||
addr = len(sys.argv) < 2 and "0.0.0.0" or sys.argv[1]
|
|
||||||
port = len(sys.argv) < 3 and 80 or int(sys.argv[2])
|
|
||||||
HandlerClass.protocol_version = Protocol
|
|
||||||
httpd = ServerClass((addr, port), HandlerClass)
|
|
||||||
sa = httpd.socket.getsockname()
|
|
||||||
print "Serving HTTP on", sa[0], "port", sa[1], "..."
|
|
||||||
httpd.serve_forever()
|
|
||||||
except:
|
|
||||||
exit()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### index.html
|
|
||||||
生成一个临时的 `index.html` 文件,其内容会被 `index.py` 更新。
|
|
||||||
```bash
|
|
||||||
$ touch index.html
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Dockerfile
|
#### Dockerfile
|
||||||
|
|
||||||
编写 `Dockerfile` 文件,内容为
|
编写 `Dockerfile` 文件,内容为
|
||||||
|
|
||||||
```docker
|
```docker
|
||||||
FROM python:2.7
|
FROM python:3.6-alpine
|
||||||
WORKDIR /code
|
|
||||||
ADD . /code
|
ADD . /code
|
||||||
EXPOSE 80
|
WORKDIR /code
|
||||||
CMD python index.py
|
RUN pip install redis flask
|
||||||
|
CMD ["python", "app.py"]
|
||||||
```
|
```
|
||||||
|
|
||||||
### haproxy 目录
|
#### docker-compose.yml
|
||||||
编写 `haproxy.cfg` 文件,内容为
|
|
||||||
```bash
|
|
||||||
global
|
|
||||||
log 127.0.0.1 local0
|
|
||||||
log 127.0.0.1 local1 notice
|
|
||||||
|
|
||||||
defaults
|
编写 `docker-compose.yml` 文件,这个是 Compose 使用的主模板文件。
|
||||||
log global
|
|
||||||
mode http
|
|
||||||
option httplog
|
|
||||||
option dontlognull
|
|
||||||
timeout connect 5000ms
|
|
||||||
timeout client 50000ms
|
|
||||||
timeout server 50000ms
|
|
||||||
|
|
||||||
listen stats
|
|
||||||
bind 0.0.0.0:70
|
|
||||||
stats enable
|
|
||||||
stats uri /
|
|
||||||
|
|
||||||
frontend balancer
|
|
||||||
bind 0.0.0.0:80
|
|
||||||
mode http
|
|
||||||
default_backend web_backends
|
|
||||||
|
|
||||||
backend web_backends
|
|
||||||
mode http
|
|
||||||
option forwardfor
|
|
||||||
balance roundrobin
|
|
||||||
server weba weba:80 check
|
|
||||||
server webb webb:80 check
|
|
||||||
server webc webc:80 check
|
|
||||||
option httpchk GET /
|
|
||||||
http-check expect status 200
|
|
||||||
```
|
|
||||||
### docker-compose.yml
|
|
||||||
编写 `docker-compose.yml` 文件,这个是 `Compose` 使用的主模板文件。内容十分简单,指定 3 个 `web` 容器,以及 1 个 `haproxy` 容器。
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: "3"
|
version: '3'
|
||||||
services:
|
services:
|
||||||
|
|
||||||
weba:
|
web:
|
||||||
build: ./web
|
build: .
|
||||||
expose:
|
|
||||||
- 80
|
|
||||||
|
|
||||||
webb:
|
|
||||||
build: ./web
|
|
||||||
expose:
|
|
||||||
- 80
|
|
||||||
|
|
||||||
webc:
|
|
||||||
build: ./web
|
|
||||||
expose:
|
|
||||||
- 80
|
|
||||||
|
|
||||||
haproxy:
|
|
||||||
image: haproxy:latest
|
|
||||||
volumes:
|
|
||||||
- ./haproxy:/haproxy-override
|
|
||||||
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
|
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "5000:5000"
|
||||||
- "70:70"
|
|
||||||
expose:
|
redis:
|
||||||
- "80"
|
image: "redis:alpine"
|
||||||
- "70"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 运行 compose 项目
|
#### 运行 compose 项目
|
||||||
现在 `compose-haproxy-web` 目录结构如下:
|
|
||||||
```bash
|
|
||||||
compose-haproxy-web
|
|
||||||
├── docker-compose.yml
|
|
||||||
├── haproxy
|
|
||||||
│ └── haproxy.cfg
|
|
||||||
└── web
|
|
||||||
├── Dockerfile
|
|
||||||
├── index.html
|
|
||||||
└── index.py
|
|
||||||
```
|
|
||||||
在该目录下执行 `docker-compose up` 命令,会整合输出所有容器的输出。
|
|
||||||
```bash
|
```bash
|
||||||
$ docker-compose up
|
$ docker-compose up
|
||||||
Recreating composehaproxyweb_webb_1...
|
|
||||||
Recreating composehaproxyweb_webc_1...
|
|
||||||
Recreating composehaproxyweb_weba_1...
|
|
||||||
Recreating composehaproxyweb_haproxy_1...
|
|
||||||
Attaching to composehaproxyweb_webb_1, composehaproxyweb_webc_1, composehaproxyweb_weba_1, composehaproxyweb_haproxy_1
|
|
||||||
```
|
```
|
||||||
|
|
||||||
此时访问本地的 `80` 端口,会经过 `haproxy` 自动转发到后端的某个 web 容器上,刷新页面,可以观察到访问的容器地址的变化。
|
此时访问本地 `5000` 端口,每次刷新页面,计数就会加 1。
|
||||||
|
|
||||||
访问本地 `70` 端口,可以查看到 `haproxy` 的统计信息。
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ version: "3"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
server:
|
server:
|
||||||
# build: ./.travis
|
|
||||||
image: yeasy/docker_practice:latest
|
image: yeasy/docker_practice:latest
|
||||||
ports:
|
ports:
|
||||||
- 4000:4000
|
- 4000:4000
|
||||||
|
@ -27,7 +26,7 @@ services:
|
||||||
|
|
||||||
development:
|
development:
|
||||||
build: ./.travis
|
build: ./.travis
|
||||||
image: yeasy/docker_practice:development
|
image: yeasy/docker_practice:latest
|
||||||
ports:
|
ports:
|
||||||
- 4000:4000
|
- 4000:4000
|
||||||
volumes:
|
volumes:
|
||||||
|
|
|
@ -98,6 +98,8 @@ $ sudo groupadd docker
|
||||||
$ sudo usermod -aG docker $USER
|
$ sudo usermod -aG docker $USER
|
||||||
```
|
```
|
||||||
|
|
||||||
|
退出当前终端并重新登录,进行如下测试。
|
||||||
|
|
||||||
### 测试 Docker 是否安装正确
|
### 测试 Docker 是否安装正确
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -144,6 +144,8 @@ $ sudo groupadd docker
|
||||||
$ sudo usermod -aG docker $USER
|
$ sudo usermod -aG docker $USER
|
||||||
```
|
```
|
||||||
|
|
||||||
|
退出当前终端并重新登录,进行如下测试。
|
||||||
|
|
||||||
### 测试 Docker 是否安装正确
|
### 测试 Docker 是否安装正确
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -102,6 +102,8 @@ $ sudo groupadd docker
|
||||||
$ sudo usermod -aG docker $USER
|
$ sudo usermod -aG docker $USER
|
||||||
```
|
```
|
||||||
|
|
||||||
|
退出当前终端并重新登录,进行如下测试。
|
||||||
|
|
||||||
### 测试 Docker 是否安装正确
|
### 测试 Docker 是否安装正确
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
@ -132,6 +132,8 @@ $ sudo groupadd docker
|
||||||
$ sudo usermod -aG docker $USER
|
$ sudo usermod -aG docker $USER
|
||||||
```
|
```
|
||||||
|
|
||||||
|
退出当前终端并重新登录,进行如下测试。
|
||||||
|
|
||||||
### 测试 Docker 是否安装正确
|
### 测试 Docker 是否安装正确
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 116 KiB |
|
@ -33,7 +33,7 @@ nameserver 114.114.114.114
|
||||||
nameserver 8.8.8.8
|
nameserver 8.8.8.8
|
||||||
```
|
```
|
||||||
|
|
||||||
如果用户想要手动指定容器的配置,可以利用下面的选项。
|
如果用户想要手动指定容器的配置,可以在使用 `docker run` 命令启动容器时加入如下参数:
|
||||||
|
|
||||||
`-h HOSTNAME` 或者 `--hostname=HOSTNAME` 设定容器的主机名,它会被写到容器内的 `/etc/hostname` 和 `/etc/hosts`。但它在容器外部看不到,既不会在 `docker ps` 中显示,也不会在其他的容器的 `/etc/hosts` 看到。
|
`-h HOSTNAME` 或者 `--hostname=HOSTNAME` 设定容器的主机名,它会被写到容器内的 `/etc/hostname` 和 `/etc/hosts`。但它在容器外部看不到,既不会在 `docker ps` 中显示,也不会在其他的容器的 `/etc/hosts` 看到。
|
||||||
|
|
||||||
|
@ -41,4 +41,4 @@ nameserver 8.8.8.8
|
||||||
|
|
||||||
`--dns-search=DOMAIN` 设定容器的搜索域,当设定搜索域为 `.example.com` 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 `host.example.com`。
|
`--dns-search=DOMAIN` 设定容器的搜索域,当设定搜索域为 `.example.com` 时,在搜索一个名为 host 的主机时,DNS 不仅搜索 host,还会搜索 `host.example.com`。
|
||||||
|
|
||||||
*注意:* 如果没有上述最后 2 个选项,Docker 会默认用主机上的 `/etc/resolv.conf` 来配置容器。
|
>注意:如果在容器启动时没有指定最后两个参数,Docker 会默认用主机上的 `/etc/resolv.conf` 来配置容器。
|
Loading…
Reference in New Issue