容器编排
我们的项目可能会使用了多个容器,容器多了之后管理容器的工作就会变得麻烦。如果要对多个容器进行自动配置使得容器可以相互协作甚至实现复杂的调度,这就需要进行容器编排。Docker原生对容器编排的支持非常弱,但是可以通过社区提供的工具来实现容器编排。
Docker Compose
可以通过安装Docker Compose工具来实现基于YAML文件的容器编排,YAML文件会定义一系列的容器以及容器运行时的属性,Docker Compose会根据这些配置来管理容器。
-
安装Docker Compose。
curl -L https://github.com/docker/compose/releases/download/1.25.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
说明:如果没有curl工具,在CentOS下可以先通过包管理工具yum安装curl再执行上面的命令。
当然我们也可以使用Python的包管理工具pip来安装Docker Compose,命令如下所示。
pip3 install -U docker-compose
-
使用Docker Compose。
我们先创建一个名为
composeapp
的文件夹并在该文件夹下创建两个子文件夹product-service
和web-site
,如下所示。mkdir composeapp cd composeapp mkdir product-service mkdir web-site
我们先在
product-service
文件夹下编写提供数据的API接口程序。vim product-service/api.py
我们用Flask来实现一个非常简单的数据接口服务程序。
from pickle import dumps, loads from flask import Flask from flask_restful import Resource, Api from redis import Redis from flask_cors import CORS app = Flask(__name__) CORS(app, resources={r'/api/*': {'origins': '*'}}) api = Api(app) redis = Redis(host='redis-master', port=6379) class Product(Resource): def get(self): data = redis.get('products') if not data: products = ['Ice Cream', 'Chocolate', 'Coca Cola', 'Hamburger'] redis.set('products', dumps(products)) else: products = loads(data) return {'products': products} api.add_resource(Product, '/api/products') if __name__ == '__main__': app.run(host='0.0.0.0', port=8000, debug=True)
由于上面的项目需要依赖
flask
、flask-restful
等三方库,所以我们再添加一个指明依赖库的文件并将其命名为requirements.txt
,其内容如下所示。vim product-service/requirements.txt flask flask-restful flask-cors redis
稍后我们会将上面的接口服务放在一个容器中运行,为此我们先编写一个Dockerfile文件以便创建对应的镜像,其内容如下所示。
vim product-service/Dockerfile FROM python:3 ADD . /root/product-service WORKDIR /root/product-service RUN pip install -r requirements.txt CMD ["python", "api.py"]
我们再去到
web-site
目录下创建一个页面,稍后我们会通一个容器来提供Nginx服务并运行该页面,而这个页面会访问我们刚才部署的数据接口服务获取数据并通过Vue.js将数据渲染到页面上。vim web-site/index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>首页</title> </head> <body> <div id="app"> <h2>产品列表</h2> <ul> <li v-for="product in products">{{ product }}</li> </ul> </div> <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script> <script> new Vue({ el: '#app', data: { products: [] }, created() { fetch('http://1.2.3.4:8000/api/products') .then(resp => resp.json()) .then(json => {this.products = json.products}) } }) </script> </body> </html>
接下来,我们要通过一个YAML文件来创建三个容器并指明容器之间的依赖关系。
vim docker-compose.yml version: '3' services: product-service: build: ./product-service ports: - '8000:8000' links: - redis-master web-site: image: nginx ports: - '80:80' volumes: - ./web-site:/usr/share/nginx/html redis-master: image: redis expose: - '6379'
有了这个YAML文件,我们就可以使用
docker-compose
命令来创建和管理这三个容器,其命令如下所示。docker-compose up Creating network "composeapp_default" with the default driver Building product-service Step 1/5 : FROM python:3 ---> e497dabd8450 Step 2/5 : ADD . /root/product-service ---> fbe62813d595 Removing intermediate container 6579e845565a Step 3/5 : WORKDIR /root/product-service ---> 3a722675e3b1 Removing intermediate container 57fc490436ce Step 4/5 : RUN pip install -r requirements.txt ---> Running in cadc2d0c1b9b ... ... ---> fc747fc11f4a Removing intermediate container cadc2d0c1b9b Step 5/5 : CMD python api.py ---> Running in ecbbd2a69906 ---> 637e760f2e5b Removing intermediate container ecbbd2a69906 Successfully built 637e760f2e5b WARNING: Image for service product-service was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Creating composeapp_redis-master_1 ... done Creating composeapp_web-site_1 ... done Creating composeapp_product-service_1 ... done Attaching to composeapp_redis-master_1, composeapp_web-site_1, composeapp_product-service_1 ... ...