What is Compose?
node
Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。经过Compose能够定义和运行多容器docker环境,使用Compose,可使用模版文件(YAML文件)来配置应用的服务。而后,经过compose相关命令,能够建立和启动全部应用服务。
python
Compose应用场景git
使用Dockerfile模版文件,能够很方便的定义一个单独的应用容器。然而,在平常工做中,常常碰到须要多个容器相互配合来完成某项任务的状况。例如,要实现一个Web项目,除了Web服务容器自己,每每还须要在加上后端的数据库服务容器,甚至还包括负载均衡容器等。Compose刚好知足这样的需求,用户经过单独的docker-compose.yml模版文件来定义一组相关联的应用容器为一个项目。
github
Compose工做原理图web
Compose中的两个重要概念:redis
服务(service):一个应用的容器,实际上能够包括若干运行相同镜像的容器 实例。docker
项目(project):由一组关联的应用容器组成的一个完整业务单元,在 docker- compose.yml 文件中定义。数据库
Compose 的默认管理对象是项目,经过子命令对项目中的一组容器进行便捷地生 命周期管理。
安装Composeflask
Compose能够安装在众多不一样的平台下,如:MacOS,Windows,Other 64-bit Linux。安装Compose方式也有不少,如pip方式安装、二进制包安装、容器中执行等等方式。后端
Linux下安装Compose
安装 Compose 以前,要先安装 Docker(须要 Docker Engine 1.7.1+)。
下载最新Compose版本:
[root@centos7 ~]# sudo curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
添加执行权限:
[root@centos7 ~]# chmod +x /usr/local/bin/docker-compose
检查安装:
[root@centos7 ~]# docker-compose --version docker-compose version 1.22.0, build f46880fe
卸载Compose
若是使用curl安装,去卸载Comose:
sudo rm /usr/local/bin/docker-compose
Compose使用
使用Compose基本上分为三步:
1.使用Dockerfile定义应用程序的环境,以即可以在任何地方进行复制。
2.在docker-compose.yml中定义构成应用程序的服务,以便它们能够在隔离环境中一块儿运行。
3.运行docker-compose up和Compose启动并运行整个应用程序。
为了实现上述编排与部署的原理,能够从Docker Comose官网上的一个例子开始入手。
第一步:设置
定义应用程序的依赖项。
1.建立项目目录:
[root@centos7 ~]# mkdir composetest [root@centos7 ~]# cd composetest
2.建立一个名为app.py的应用,内容以下:
[root@centos7 composetest]# cat app.py #!/usr/bin/python3 # coding=utf-8 import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count) if __name__ == "__main__": app.run(host="0.0.0.0", debug=True)
这是一个基于Python的轻Web的Flask应用,因此看到应用里有.route('/'),即反问根目录,而后返回一个从Redis里读取出来的值,该值经过自加来统计访问次数。最后Web容器在0.0.0.0上监听默认端口5000.
3.建立另外一个文件名为requirements.txt指定python依赖包:flask和redis,内容以下:
[root@centos7 composetest]# cat requirements.txt flask redis
第二步:建立一个Dockerfile文件
咱们来写一个 Dockerfile 来定义 Docker 镜像,此镜像包含了 Python 的依赖包和 Python 环境。
一样在此目录下,咱们建立一个 Dockerfile 文件。
[root@centos7 composetest]# cat Dockerfile FROM python:3.4-alpine ADD . /code WORKDIR /code RUN pip install -r requirements.txt CMD ["python3", "app.py"]
注:我本地环境使用python2.7和python3兼容模式,因此须要指定python3去执行app.py文件。
代码表示“:
继承python3.4基础镜像
将当前目录.影射到/code下
设置工做目录/code
安装python依赖关系包
启动app应用程序
第三步:Compose文件定义服务
建立一个名为docker-compose.yml文件,内容以下:
[root@centos7 composetest]# cat docker-compose.yml version: '3' services: web: build: . ports: - "5000:5000" redis: image: "redis:alpine"
Compose文件定义了两个服务,web服务和redis服务,web服务:
使用从当前目录中的Dockerfile构建的映像。
将容器上的公开端口5000转发到主机上的端口5000。 咱们使用Flask Web服务器的默认端口5000。
redis服务使用从Docker Hub注册表中提取的公共Redis映像。
这里是编排部署核心所在,在这个YAML文件里,能够看到高级别的key:web和redis,这意味着用Compose定义了由两个“服务”组成的Docker集群。其中第一个服务叫web,它从当前目录的Dockerfile build获得;以后在容器中运行python app.py;把容器内的5000端口映射到宿主机的5000端口;挂载执行这些操做所在的目录到容器/code目录下。以后,代码修改就在容器中体现。
第二个服务redis直接使用已有的redis镜像,Dockerfile没必要另外编写。
接下来执行一句docker-compose up就能够了,尝试访问一下宿主机的5000端口,若是没什么问题能看到容器里的python web服务统计访问次数了。
第四步:Comose构建和运行应用
在项目目录中,经过docker-compose up命令运行应用服务。
[root@centos7 composetest]# docker-compose up WARNING: The Docker Engine you're using is running in swarm mode. Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node. To deploy your application across the swarm, use `docker stack deploy`. Creating network "composetest_default" with the default driver Building web Step 1/5 : FROM python:3.4-alpine 3.4-alpine: Pulling from library/python 4fe2ade4980c: Pull complete 7cf6a1d62200: Pull complete 599ae3a07d9d: Pull complete 1acdc2ab10cd: Pull complete 2c4249dd0b02: Pull complete Digest: sha256:7087f61b8d11919f24d7f6115327683a85aecaa050019bd4b35042261e8d7773 Status: Downloaded newer image for python:3.4-alpine ---> 90d3f9764c4d Step 2/5 : ADD . /code ---> 97ce6a2665ed Step 3/5 : WORKDIR /code ---> Running in b959e84e8dcc Removing intermediate container b959e84e8dcc ---> 85d8fefdf4ff Step 4/5 : RUN pip install -r requirements.txt ---> Running in 2b07e63ee082 Collecting flask (from -r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl (91kB) Collecting redis (from -r requirements.txt (line 2)) Downloading https://files.pythonhosted.org/packages/3b/f6/7a76333cf0b9251ecf49efff635015171843d9b977e4ffcf59f9c4428052/redis-2.10.6-py2.py3-none-any.whl (64kB) Collecting Jinja2>=2.10 (from flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB) Collecting itsdangerous>=0.24 (from flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz (46kB) Collecting click>=5.1 (from flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB) Collecting Werkzeug>=0.14 (from flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB) Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->flask->-r requirements.txt (line 1)) Downloading https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz Building wheels for collected packages: itsdangerous, MarkupSafe Running setup.py bdist_wheel for itsdangerous: started Running setup.py bdist_wheel for itsdangerous: finished with status 'done' Stored in directory: /root/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5 Running setup.py bdist_wheel for MarkupSafe: started Running setup.py bdist_wheel for MarkupSafe: finished with status 'done' Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46 Successfully built itsdangerous MarkupSafe Installing collected packages: MarkupSafe, Jinja2, itsdangerous, click, Werkzeug, flask, redis Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-7.0 flask-1.0.2 itsdangerous-0.24 redis-2.10.6 Removing intermediate container 2b07e63ee082 ---> 23354c79c570 Step 5/5 : CMD ["python3", "app.py"] ---> Running in 1de84ec9dcd3 Removing intermediate container 1de84ec9dcd3 ---> 1cdd437daa30 Successfully built 1cdd437daa30 Successfully tagged composetest_web:latest WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`. Pulling redis (redis:alpine)... alpine: Pulling from library/redis 4fe2ade4980c: Already exists fb758dc2e038: Pull complete 989f7b0c858b: Pull complete d5318f13abaa: Pull complete 3521559474dd: Pull complete af5d048338ef: Pull complete Digest: sha256:fc78e96c8036b6fa69ce8d4e811ba84b9278e772047a93fb6d5549de4ddecc32 Status: Downloaded newer image for redis:alpine Creating composetest_redis_1 ... done Creating composetest_web_1 ... done Attaching to composetest_redis_1, composetest_web_1 redis_1 | 1:C 27 Sep 08:31:29.854 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo redis_1 | 1:C 27 Sep 08:31:29.854 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=1, just started redis_1 | 1:C 27 Sep 08:31:29.854 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf redis_1 | 1:M 27 Sep 08:31:29.857 # Not listening to IPv6: unsupproted redis_1 | 1:M 27 Sep 08:31:29.857 * Running mode=standalone, port=6379. redis_1 | 1:M 27 Sep 08:31:29.857 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. redis_1 | 1:M 27 Sep 08:31:29.858 # Server initialized redis_1 | 1:M 27 Sep 08:31:29.858 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. redis_1 | 1:M 27 Sep 08:31:29.858 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled. redis_1 | 1:M 27 Sep 08:31:29.858 * Ready to accept connections web_1 | * Serving Flask app "app" (lazy loading) web_1 | * Environment: production web_1 | WARNING: Do not use the development server in a production environment. web_1 | Use a production WSGI server instead. web_1 | * Debug mode: on web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) web_1 | * Restarting with stat web_1 | * Debugger is active! web_1 | * Debugger PIN: 830-423-564
查看本地网络状态,并访问http://127.0.0.1:5000,以下:
浏览器中访问docker主机ip,每次刷新网页会有一个计数:
此时列出镜像列表会返回redis和web:
中止应用,能够在工做目录中经过docker-compose down中止服务,或者在启动应用的窗口中经过CTRL+C中止应用:
[root@centos7 composetest]# docker-compose down Stopping composetest_web_1 ... done Stopping composetest_redis_1 ... done Removing composetest_web_1 ... done Removing composetest_redis_1 ... done Removing network composetest_default
第五步:编辑Comose文件添加绑定挂载
编辑项目目录中的docker-compose.yml文件,为web服务添加绑定挂载:
[root@centos7 composetest]# cat docker-compose.yml version: '3' services: web: build: . ports: - "5000:5000" volumes: - .:/code redis: image: "redis:alpine"
新键值对volumes是将本地的项目目录composetest挂载到容器内的/code目录下,这样能够动态的修改代码,从而没必要在从新建立镜像。
第六步:使用compose从新建立和运行应用
使用docker-compose up从新建立应用:
[root@centos7 composetest]# docker-compose up WARNING: The Docker Engine you're using is running in swarm mode. Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node. To deploy your application across the swarm, use `docker stack deploy`. Recreating composetest_web_1 ... done Starting composetest_redis_1 ... done Attaching to composetest_redis_1, composetest_web_1 redis_1 | 1:C 28 Sep 01:46:01.941 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo redis_1 | 1:C 28 Sep 01:46:01.942 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=1, just started redis_1 | 1:C 28 Sep 01:46:01.942 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf redis_1 | 1:M 28 Sep 01:46:01.944 # Not listening to IPv6: unsupproted redis_1 | 1:M 28 Sep 01:46:01.945 * Running mode=standalone, port=6379. redis_1 | 1:M 28 Sep 01:46:01.945 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. redis_1 | 1:M 28 Sep 01:46:01.945 # Server initialized redis_1 | 1:M 28 Sep 01:46:01.945 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. redis_1 | 1:M 28 Sep 01:46:01.945 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled. redis_1 | 1:M 28 Sep 01:46:01.945 * DB loaded from disk: 0.000 seconds redis_1 | 1:M 28 Sep 01:46:01.945 * Ready to accept connections web_1 | * Serving Flask app "app" (lazy loading) web_1 | * Environment: production web_1 | WARNING: Do not use the development server in a production environment. web_1 | Use a production WSGI server instead. web_1 | * Debug mode: on web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) web_1 | * Restarting with stat web_1 | * Debugger is active! web_1 | * Debugger PIN: 328-944-619 web_1 | 192.168.39.1 - - [28/Sep/2018 01:46:13] "GET / HTTP/1.1" 200 - web_1 | * Detected change in '/code/app.py', reloading web_1 | * Restarting with stat web_1 | * Debugger is active! web_1 | * Debugger PIN: 328-944-619 web_1 | 192.168.39.1 - - [28/Sep/2018 01:49:48] "GET / HTTP/1.1" 200 -
第七步:修改应用
如今,app.py代码能够直接编辑app.py进行修改,如:
return 'Hello World from docker! I have been seen {} times.\n'.format(count)
从新刷新,浏览器:
第八步:尝试一些其余命令
若是你但愿你的应用程序在后台运行,你能够将 -d 标记传递给 docker-compose up 并使用 docker-compose ps 来查看当前运行的应用。
$ docker-compose up -d Starting composetest_redis_1... Starting composetest_web_1... $ docker-compose ps Name Command State Ports ------------------------------------------------------------------- composetest_redis_1 /usr/local/bin/run Up composetest_web_1 /bin/sh -c python app.py Up 5000->5000/tcp
docker-compose run
命令容许你为你的应用程序运行一次性命令。例如,查看哪些环境变量能够用于 web 服务:
$ docker-compose run web env
经过 docker-compose --help
查看全部可用的命令。
若是你使用 docker-compose up -d
启动了 Compose,你可能但愿在它们运行完成后中止服务:
$ docker-compose stop
你能够停掉全部一切,使用 down 命令彻底移除容器。传递 —volumes 还能够删除 Redis 容器中所使用的数据卷。
$ docker-compose down --volumes
这时,你已经看到了 Compose 工做的基础知识。
Compose工做原理
Docker-compose的调用过程很是的扁平,以下图所示。
图1.compose的一次调用流程
以docker-compose up操做为例,docker-compose更像是docker client加强版,它为docker client引入“组”的概念,如上图所示docker-comose定义了一组“服务”来组成一个docker-comose的project,在经过service创建docker-comose.yml参数,从而与container创建关系,最后使用container来完成对docker-py(Docker client的python版)的调用,向 Daemon发起HTTP请求。
首先,用户执行的docker-comose up指令调用了命令行的启动方式。一个docker-compose.yml定义了一个docker-compose的project,docker-compose up操做提供的命令行参数做为想这个Project的启动参数交由project模块去处理。
而后,若是当前宿主机已经存在与该应用对应的容器,docker-comose将进行行为逻辑判断。若是用户指定能够从新启动已有服务,docker-comose就会执行service模块的容器重启方式,不然就将直接启动已有容器。这两种操做的区别在于前者会中止旧的容器,建立启动新的容器,并把旧容器移除掉。在这个过程当中建立容器的各项自定义参数都是从docker-compose up指令和docker-compose.yml中传入。
接下来,这个方法中完成了一个Docker容器启动所需的主要参数的封装,并在Container模块执行启动。
最后,container模块会调用docker-py客户端来执行向Docker daemon发起建立容器的POST请求,在交由Docker处理。
未完待续..
参考:https://docs.docker.com/compose/overview/
Docker容器与容器云