From 8939af4f97572fa041f2d89bcd37017cc00e12fb Mon Sep 17 00:00:00 2001 From: khs1994 Date: Sun, 10 Dec 2017 11:52:09 +0800 Subject: [PATCH] Update compose #288 --- CHANGELOG.md | 2 + compose/demo/app/Dockerfile | 5 + compose/demo/app/app.py | 13 ++ compose/demo/app/docker-compose.yml | 10 + .../compose-haproxy-web/docker-compose.yml | 29 --- .../compose-haproxy-web/haproxy/haproxy.cfg | 32 --- .../demo/compose-haproxy-web/web/Dockerfile | 5 - compose/demo/compose-haproxy-web/web/index.py | 68 ------ compose/usage.md | 198 +++--------------- 9 files changed, 63 insertions(+), 299 deletions(-) create mode 100644 compose/demo/app/Dockerfile create mode 100644 compose/demo/app/app.py create mode 100644 compose/demo/app/docker-compose.yml delete mode 100644 compose/demo/compose-haproxy-web/docker-compose.yml delete mode 100644 compose/demo/compose-haproxy-web/haproxy/haproxy.cfg delete mode 100644 compose/demo/compose-haproxy-web/web/Dockerfile delete mode 100644 compose/demo/compose-haproxy-web/web/index.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dd199a..1326ad7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * 0.9-rc3: 2017-12-20 + * 精简示例代码 + * 调整目录结构 * 0.9-rc2: 2017-12-10 diff --git a/compose/demo/app/Dockerfile b/compose/demo/app/Dockerfile new file mode 100644 index 0000000..7c4b8c7 --- /dev/null +++ b/compose/demo/app/Dockerfile @@ -0,0 +1,5 @@ +FROM python:3.6-alpine +ADD . /code +WORKDIR /code +RUN pip install redis flask +CMD ["python", "app.py"] diff --git a/compose/demo/app/app.py b/compose/demo/app/app.py new file mode 100644 index 0000000..f0dfc20 --- /dev/null +++ b/compose/demo/app/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) diff --git a/compose/demo/app/docker-compose.yml b/compose/demo/app/docker-compose.yml new file mode 100644 index 0000000..f2a202f --- /dev/null +++ b/compose/demo/app/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3' +services: + + web: + build: . + ports: + - "5000:5000" + + redis: + image: "redis:alpine" diff --git a/compose/demo/compose-haproxy-web/docker-compose.yml b/compose/demo/compose-haproxy-web/docker-compose.yml deleted file mode 100644 index 46c0841..0000000 --- a/compose/demo/compose-haproxy-web/docker-compose.yml +++ /dev/null @@ -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" diff --git a/compose/demo/compose-haproxy-web/haproxy/haproxy.cfg b/compose/demo/compose-haproxy-web/haproxy/haproxy.cfg deleted file mode 100644 index 99251ed..0000000 --- a/compose/demo/compose-haproxy-web/haproxy/haproxy.cfg +++ /dev/null @@ -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 diff --git a/compose/demo/compose-haproxy-web/web/Dockerfile b/compose/demo/compose-haproxy-web/web/Dockerfile deleted file mode 100644 index d0e74cd..0000000 --- a/compose/demo/compose-haproxy-web/web/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM python:2.7 -WORKDIR /code -ADD . /code -EXPOSE 80 -CMD python index.py diff --git a/compose/demo/compose-haproxy-web/web/index.py b/compose/demo/compose-haproxy-web/web/index.py deleted file mode 100644 index d274ec9..0000000 --- a/compose/demo/compose-haproxy-web/web/index.py +++ /dev/null @@ -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("

HA Webpage Visit Results

") - 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("

#"+ str(request[pair][1]) +": "+str(request[pair][0])+ " requests " + "from <"+guest+"> to WebServer <"+pair[1]+">

") - else: - file.write("

#"+ str(request[pair][1]) +": "+str(request[pair][0])+ " requests " + "from <"+guest+"> to WebServer <"+pair[1]+">

") - file.write(" ") - 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() diff --git a/compose/usage.md b/compose/usage.md index 6001b2f..593b754 100644 --- a/compose/usage.md +++ b/compose/usage.md @@ -1,6 +1,7 @@ ## 使用 ### 术语 + 首先介绍几个术语。 * 服务 (`service`):一个应用容器,实际上可以运行多个相同镜像的实例。 @@ -10,197 +11,64 @@ 可见,一个项目可以由多个服务(容器)关联而成,`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 -#!/usr/bin/python -#authors: yeasy.github.com -#date: 2013-07-05 +from flask import Flask +from redis import Redis -import sys -import BaseHTTPServer -from SimpleHTTPServer import SimpleHTTPRequestHandler -import socket -import fcntl -import struct -import pickle -from datetime import datetime -from collections import OrderedDict +app = Flask(__name__) +redis = Redis(host='redis', port=6379) -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("

HA Webpage Visit Results

") - 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("

#"+ str(request[pair][1]) +": "+str(request[pair][0])+ " requests " + "from <"+guest+"> to WebServer <"+pair[1]+">

") - else: - file.write("

#"+ str(request[pair][1]) +": "+str(request[pair][0])+ " requests " + "from <"+guest+"> to WebServer <"+pair[1]+">

") - file.write(" ") - file.close() - pickle.dump(request,open("pickle_data.txt","w")) +@app.route('/') +def hello(): + count = redis.incr('hits') + return 'Hello World! 该页面已被访问 {} 次。\n'.format(count) -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() -``` - -#### index.html -生成一个临时的 `index.html` 文件,其内容会被 `index.py` 更新。 -```bash -$ touch index.html +if __name__ == "__main__": + app.run(host="0.0.0.0", debug=True) ``` #### Dockerfile + 编写 `Dockerfile` 文件,内容为 + ```docker -FROM python:2.7 -WORKDIR /code +FROM python:3.6-alpine ADD . /code -EXPOSE 80 -CMD python index.py +WORKDIR /code +RUN pip install redis flask +CMD ["python", "app.py"] ``` -### haproxy 目录 -编写 `haproxy.cfg` 文件,内容为 -```bash -global - log 127.0.0.1 local0 - log 127.0.0.1 local1 notice +#### docker-compose.yml -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 -``` -### docker-compose.yml -编写 `docker-compose.yml` 文件,这个是 `Compose` 使用的主模板文件。内容十分简单,指定 3 个 `web` 容器,以及 1 个 `haproxy` 容器。 +编写 `docker-compose.yml` 文件,这个是 Compose 使用的主模板文件。 ```yaml -version: "3" +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 + web: + build: . ports: - - "80:80" - - "70:70" - expose: - - "80" - - "70" + - "5000:5000" + + redis: + image: "redis:alpine" ``` -### 运行 compose 项目 -现在 `compose-haproxy-web` 目录结构如下: -```bash -compose-haproxy-web -├── docker-compose.yml -├── haproxy -│ └── haproxy.cfg -└── web - ├── Dockerfile - ├── index.html - └── index.py -``` -在该目录下执行 `docker-compose up` 命令,会整合输出所有容器的输出。 +#### 运行 compose 项目 + ```bash $ 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 容器上,刷新页面,可以观察到访问的容器地址的变化。 - -访问本地 `70` 端口,可以查看到 `haproxy` 的统计信息。 +此时访问本地 `5000` 端口,每次刷新页面,计数就会加 1。