docker 集群(单主机)部署web 应用入门(Nginx)
	本文探讨的场景是使用 Nginx 部署一个应用,可能涉及 Nginx 服务,web 服务,web service 服务,缓存服务,数据库服务等,这时就需要多个容器协作,这些容器之间依赖关系非常复杂。面对动态地址,我们难以检查每个容器网络地址,然后做配置。这里仅是简单介绍单机 Docker compose 的应用。 
	 
	准备环境
	- 
		假设你比较熟悉 docker run 等命令
 
	- 
		简单了解 Nginx 的配置
 
	- 
		下载 Nginx 并检查1
 
 
sudo docker pull nginx
sudo docker run -d --name ng1 -p 8080:80 nginx
curl http://localhost:8080/
sudo docker rm -f ng1 
	(重要)检查 pip 与 Python 版本一致性 
pip --version
python --version 
 
 
	如果没有 pip 的 python 与 python 版本不一致, 需要安装/重新 pip 
进入 https://pip.pypa.io/en/stable/installing/ 右键保存 get-pip.py 文件
python get-pip.py 
 
	安装检查 docker compose,更多细节参考2: 
pip install docker-compose
docker-compose --version 
	 
	1、docker compose 简介
	
		用一个 docker-compose.yml 文件配置多个 docker 应用服务,用一个简单命令创建并启动这些应用。 
 
	官方很解释简洁。让我们看 docker-compose.yml (YAML 是对程序员友好的数据序列化标准3)的案例: 
version: '2'
services:
  web:
    build: .
    ports:
    - "5000:5000"
    volumes:
    - .:/code
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
 
 
 
	这文本层次结构,定义了两个服务(services,注:docker 就概念是 Container,随着服务概念的兴起,新的说法是一个服务一个容器)分别是 web 和 Redis,和一个 docker 卷;这些命令几乎不用解释,与 docker run , docker create 等命令类似,例如 port 就是 -p 参数,详细参考:Compose file reference 
	* 官方的快速指南* 
	1、创建工作目录 
mkdir composetest
cd composetest 
 
 
 
	2、创建 python 的 web 应用 app.py 
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! I have been seen {} times.\n'.format(count)
if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)
 
 
 
	3、创建 Dockerfile 
FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install flask redis
CMD ["python", "app.py"] 
 
 
	这个文件告诉 docker 构建一个新的镜像采用的配置: 
	- 
		基础配置来源 python:3.4-alpine
 
	- 
		把当前目录添加入镜像中 /code 路径下
 
	- 
		设置镜像启动时当前工作目录 /code
 
	- 
		在镜像中安装 python 的 flask web 框架 与 redis 访问客户端
 
	- 
		启动时执行命令 python app.py
 
 
	4、用 Compose 创建镜像并运行 
	按上述内容创建 docker-compose.yml。 
	运行 
sudo docker-compose up
sudo docker ps 
 
 
	看到几个服务(容器)按要求启动。输入: 
curl http://localhost:5000 
 
 
	返回结果:Hello World! I have been seen 1 times. 
	 
	 
	 
	2、核心服务-app 网络
	在 python 程序中,代码 redis = Redis(host=’redis’, port=6379) 中 host=’redis’  这里没有用绝对地址!!!,事实上,你进入其中任何一个容器,ping redis, ping web  都是通的哦。 
	官方文档 docker-compose  为每个项目默认建立 [projectname]_default 网络,使得服务之间可以方便的通讯。 
	 
	 
	 
	3、Nginx 部署 web 应用
	 
	 
	3.1 清除所有服务(容器)
sudo docker rm -f $(sudo docker ps -a -q) 
	 
	 
	3.2 了解 Nginx 容器文件空间
sudo docker run -it --rm nginx /bin/bash 
	进入 nginx 容器。按官网信息查看目录和文件: 
	- 
		/etc/nginx 各种配置文件,其中 nginx.conf 是主配置文件,一般不需要修改
 
	- 
		/etc/nginx/conf.d 虚拟机配置目录。只有一个 default.conf 文件
 
	- 
		/usr/share/nginx/html 官方推荐静态文件挂载点
 
 
	在 ~/composetest 目录下,执行 
sudo docker cp 9899eb303ff6:/etc/nginx/conf.d $(pwd)/conf.d 
 
 
	这时本地有了配置虚拟机的模板。 
	 
	 
	 
	3.3 修改 docker-compose.yml 配置
	添加 nginx 和 web 服务: 
version: '2'
services:
  nginx:
    image: nginx
    volumes:
    - ./conf.d:/etc/nginx/conf.d
    ports:
    - "8080:80"
    links:
    - web1
    - web2
  web1:
    image: web1:1.0
    links:
    - redis
  web2:
    image: web1:2.0
    volumes:
    - logvolume01:/var/log
    links:
    - redis
  redis:
    image: redis
volumes:
  logvolume01: {}
	构建 web 镜像 
sudo docker build . -t web1:1.0 
	修改 app.py 的输出语句,例如将 “I” 改为 “They” 以区别镜像。然后: 
sudo docker build . -t web1:2.0 
 
	启动服务并测试: 
sudo docker-compose up
打开新终端
curl http://localhost:8080
sudo docker ps
找到 nginx 服务的 ID, 例如:b4372021a8e1。进入该容器
sudo docker exec -it b4372021a8e1 /bin/bash
ping web1 -c4
ping web2 -c4
ping redis -c4
exit 
	按 ctrl+c 终止容器服务,清除所有服务。 
	 
	 
	3.4 修改 conf.d/default.conf
upstream backends {
    server web1:5000;
    server web2:5000;
}
server {
    listen       80;
    server_name  localhost;
    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;
    location = / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    #error_page  404              /404.html;
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
    # proxy to webs
    location = /test {
        proxy_pass    http://backends/;
    }
}
	- 
		upstream backends 定义了参与 web 负载均衡的服务。详细 upstream 配置
 
	- 
		location 定义了不同 url 的处理。详细nginx location匹配规则
 
	- 
		proxy_pass 定义了代理对象。注意 有url 和 无url 的区别(rewrite,transport)。详细proxy_pass
 
 
	3.5 运行程序 
sudo docker-compose up 
	请特别注意每个服务输出,特别是 Nginx 的输出,如果 Nginx 先启动,可能会报错找不到 web 服务器 
	服务启动顺序 ,up函数,得到当前工程中的所有服务,并根据服务的依赖性(links,external links – 本工程或docker-compose之外的容器,多用于多项目共用容器,网络容器net-from以及数据容器volume-from)进行排序。 
	案例 docker-compose.yml 实际启动顺序: 
Creating composetest_redis_1
Creating composetest_web2_1
Creating composetest_web1_1
Creating composetest_nginx_1
... ... 
	测试输出: 
[~]$ curl http://localhost:8080/test
Hello World! I have been seen 1 times.
[~]$ curl http://localhost:8080/test
Hello World! They have been seen 2 times.
[~]$ curl http://localhost:8080/test
Hello World! I have been seen 3 times.
[~]$ curl http://localhost:8080/test
Hello World! They have been seen 4 times. 
	 
	 
	小结
	docker compose 使用配置文件启动服务集群,并提供集群内部网络支持,方便了部署。  由于服务之间的依赖关系,必须正确显式定义依赖(利用 links 等),减少不确定性 bug。 
	【参考】 
	 
	
		- 
			Deploying NGINX and NGINX Plus with Docker https://www.nginx.com/blog/deploying-nginx-nginx-plus-docker/
 
		- 
			Install Docker Compose. https://docs.docker.com/compose/install/
 
		- 
			http://yaml.org/
 
	 
 
 
 
 
 
 
 
      (责任编辑:IT) |