Compose
Compose是Docker的官方的开源项目,负责实现对Docker的容器快速编排,前面我们知道Fig的团队进入了Docker,而Compose就是Fig的升级版本,它的前身就是Fig,Compose兼容Fig的模版文件。
Compose中有两个重要的概念:
- 服务(service):一个应用的容器,实际可以包括若干运行相同镜像的容器实例。
- 项目(object):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。
Compose项目由Python编写,实际调用Docker服务提供的API来对容器进行管理,因此,只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。
Compose的安装
- pip
1
~]# pip install -y docker-compose
2
之后可以添加bash补全命令
3
~]# curl -L https://raw.githubusercontent.com/docker/compose/1.8.0/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
- 二进制包
1
~]# curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
2
~]# chmod a+x /usr/local/bin/docker-compose
Compose命令说明
1 | ~]# docker-compose -h |
2 | Define and run multi-container applications with Docker. |
3 | |
4 | Usage: |
5 | docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...] |
6 | docker-compose -h|--help |
7 | |
8 | Options: |
9 | -f, --file FILE Specify an alternate compose file (default: docker-compose.yml) #指定Compose模板文件,默认docker-compose.yml,可以指多个 |
10 | -p, --project-name NAME Specify an alternate project name (default: directory name) #指定项目名称,默认是其父目录的项目名 |
11 | --verbose Show more output |
12 | --no-ansi Do not print ANSI control characters |
13 | -v, --version Print version and exit |
14 | -H, --host HOST Daemon socket to connect to #指定docker daemon的套接字接口 |
15 | |
16 | --tls Use TLS; implied by --tlsverify |
17 | --tlscacert CA_PATH Trust certs signed only by this CA |
18 | --tlscert CLIENT_CERT_PATH Path to TLS certificate file |
19 | --tlskey TLS_KEY_PATH Path to TLS key file |
20 | --tlsverify Use TLS and verify the remote |
21 | --skip-hostname-check Don't check the daemon's hostname against the name specified |
22 | in the client certificate (for example if your docker host |
23 | is an IP address) |
24 | --project-directory PATH Specify an alternate working directory #指定项目的工作目录 |
25 | (default: the path of the Compose file) |
26 | |
27 | Commands: |
28 | build Build or rebuild services #build Dockefile,构造项目中的服务容器 |
29 | bundle Generate a Docker bundle from the Compose file |
30 | config Validate and view the Compose file #显示compose所写的配置文件 |
31 | create Create services #创建一个服务 |
32 | down Stop and remove containers, networks, images, and volumes #停止并且移除容器,网络,镜像,数据卷 |
33 | events Receive real time events from containers #结束容器的实时事件 |
34 | exec Execute a command in a running container #在一个运行的容器中运行命令 |
35 | help Get help on a command |
36 | images List images #列出编排任务的所需要的镜像 |
37 | kill Kill containers |
38 | logs View output from containers |
39 | pause Pause services #暂停服务 |
40 | port Print the public port for a port binding |
41 | ps List containers |
42 | pull Pull service images |
43 | push Push service images |
44 | restart Restart services |
45 | rm Remove stopped containers |
46 | run Run a one-off command |
47 | scale Set number of containers for a service #设置指定服务运行的容器个数 |
48 | start Start services |
49 | stop Stop services |
50 | top Display the running processes |
51 | unpause Unpause services |
52 | up Create and start containers |
53 | version Show the Docker-Compose version information |
- build
构建服务容器的镜像,可以随时在项目目录下运行docker-compose build来重构服务
options:
–force-rm 删除构建过程中的临时容器
–no-cache 构建镜像过程中不使用cache
–pull 始终尝试pull来获得更新版本的镜像
- kill
通过信号来强制停止服务容器,支持通过-s参数来发送信号。
- logs
查看服务容器的输出,默认情况下docker-compose将对不同的服务输出使用不同的颜色来区分,可以使用–no-color来关闭颜色,还可以使用-f选项来达到tail -f的效果。
- port
打印某个容器端口所映射的公共端口。
options:
–protocol=proto 指定端口协议,tcp(默认值)或者udp
–index=index 如果同一个服务存在多个容器,指定命令对象容器的序号(默认为1)
- run
默认情况下,如果存在关联,则所以的关联服务将会自动被启动,该命令类似启动容器后运行指定的命令,相关卷、链接等都会按照配置自动创建。
如果不希望自动启动关联的容器,可以使用–no-deps选项。
options:
-d 后台运行容器。
–name NAME 为容器指定一个名字。
–entrypoint CMD 覆盖默认的容器启动指令。
-e KEY=VAL 设置环境变量值,可多次使用选项来设置多个环境变量。
-u, –user=”” 指定运行容器的用户名或者 uid。
–no-deps 不自动启动关联的服务容器。
–rm 运行命令后自动删除容器,d 模式下将忽略。
-p, –publish=[] 映射容器端口到本地主机。
–service-ports 配置服务端口并映射到本地主机。
-T 不分配伪 tty,意味着依赖 tty 的指令将无法运行。
- scale
指定服务运行的容器个数
1 | dicker-compose scale web=3 db=2 |
- up
该命令将尝试自动完成包括构建镜像,重新创建服务,启动服务,并关联相关容器等一系列操作。链接的服务都将被自动启动,可以说一个命令就可以创建出一个项目,默认up命令会监听在前台,可以使用docker-compose up -d来监听在后台。默认docker-compose up将会尝试停止容器,然后重新创建,如果用户不希望容器被停止并重新创建,可以使用docker-compose up –no-recreate。这样将只会启动处于停止状态的容器,而忽略已经运行的服务,如果想要只是重新部署某个服务,可以使用docker-compose up –no-deps -d来重新停止并创建服务。
options:
-d 在后台运行服务容器。
–no-color 不使用颜色来区分不同的服务的控制台输出。
–no-deps 不启动服务所链接的容器。
–force-recreate 强制重新创建容器,不能与 –no-recreate 同时使用。
–no-recreate 如果容器已经存在了,则不重新创建,不能与 –force-recreate 同时使用。
–no-build 不自动构建缺失的服务镜像。
-t, –timeout TIMEOUT 停止容器时候的超时(默认为 10 秒)。
Compose环境变量
1 | - COMPOSE_PROJECT_NAME |
2 | 设置Compose的项目名称,默认是当前工作目录(docker-compose.yml所在目录)的名字,Compose会为每一个容器前添加项目名称。例如一个名称为project的项目,其中一个web容器,名称为project_web_1。 |
3 | - COMPOSE_FILE |
4 | 设置要使用的docker-compose.yml的路径。如果不存在,默认会先查找当前工作目录下是否存在docker-compose.yml,会继续向上层查找。 |
5 | - COMPOSE_API_VERSION |
6 | 某些情况下,Compose发出的Docker请求的版本可能Docker服务端并不支持,可以通过指定API版本临时解决问题,但生产环境不允许。 |
7 | - DOCKER_HOST |
8 | 设置Docker服务的监听地址。 |
9 | - DOCKER_TLS_VERIFY |
10 | 如果该环境变量不为空,则与Docker服务端的所有交互都通过TLS协议进行加密。 |
11 | - DOCKER_CERT_PATH |
12 | 配置TLS通信所需要的验证文件的路径,默认(~/.docker/)。 |
13 | - COMPOSE_HTTP_TIMEOUT |
14 | Compose发送Docker服务端的请求的超时,默认为60秒。 |
Compose模板文件
模版文件是整个Compose的核心,涉及的指令会比较多,幸运的是我们可以像理解docker run一样去理解这些指令。
默认的模版文件名称为docker-compose.yml,格式为YMAL格式,我接触过ansible-playbook所以这样的文件不是很难。
在旧版本的(version 1)中,这种版本与Fig.yml一样,例如:
1 | webapp: |
2 | image: example/web |
3 | ports: |
4 | - "80:80" |
5 | volumes: |
6 | - "/data" |
在版本2的时候扩展了Compose的语法。同时尽量保持跟版本1的兼容,如:
1 | version: "2" |
2 | services: |
3 | webapp: |
4 | image: example/web |
5 | ports: |
6 | - "80:80" |
7 | volumes: |
8 | - "/data" |
注意:每个服务都必须通过image指令指定镜像或build指令(需要Dockerfile)来自动构建生成镜像。
build
指定Dokcerfile 所在文件夹的路径,用来生成服务的基础镜像。
1 | build: /path/to/Dockerfile/ |
cap_add,cap_drop
指定容器的内核能力(capacity)分配。
例如,让容器拥有所有能力可以指定:
1 | cap_add: |
2 | - ALL |
弃掉NET_ADMIN能力:
1 | cap_drop: |
2 | - NET_ADMIN |
command
覆盖容器启动默认执行的命令。
1 | command: echo "hello world" |
container_name
指定生成的容器的名字,默认 ‘项目名’-‘服务名称’-‘序号’ 这样的格式。
注意,指定容器名称后,服务将无法进行scale,docker不允许存在相同容器名称的容器。
devices
指定映射关系。
1 | devices: |
2 | - "/dev/cdrom:/dev/cdrom" |
dns
自定义dns服务器。
1 | dns: |
2 | - 8.8.8.8 |
dns_search
配置dns搜索域。
1 | dns_search: |
2 | - example.com |
dockerfile
如果需要指定额外编译的Dockerfile文件,可以通过该指令指定。
env_file
从文件中获取环境变量,可以为单独的文件路径或列表。
1 | env_file: |
2 | - ./web/env.env |
如果与environment相互冲突,则已后者为准。
environment
设置环境变量,可以是列表,也可以是字典。
1 | environment: |
2 | - RACK_ENV=development |
如果变量值中出现true或者false等布尔值,最好放在引号中,避免与yaml解析成对应的布尔
expose
暴露端口,但不映射端口。
1 | expose: |
2 | - "3000" |
extends
基于其他模版文件进行扩展
1 | wenapp: |
2 | build: ./webapp |
1 | web: |
2 | extends: |
3 | file: common.yml |
4 | service: webapp |
5 | ports: |
6 | - "8000:8000" |
7 | links: |
8 | - db |
9 | db: |
10 | images: mysql |
后者会自动继承common.yml的内容。
使用extends需要注意:
- 要避免出现循环依赖
- extends不会继承links和volumes_from中定义的容器和数据卷容器
external_links
链接到docker-compose.yml外部的容器,甚至并非compose管理的外部容器。
extra_hosts
类似与docker中的–add-host参数,额外指定的hosts文件中的名称映射信息。
1 | extra_hosts: |
2 | - "googledns:8.8.8.8" |
会被写入容器的/etc/hosts
log_driver
类似docker中的–log-driver参数,指定日志驱动类型
1 | log_driver: "json-file" |
2 | log_driver: "syslog" |
3 | log_driver: "none" |
log_opt
日志驱动的相关参数。
1 | log_driver: "syslog" |
2 | log_opt: |
3 | syslog-address: "tcp://10.211.55.3:123" |
images
指定镜像名称或镜像id。
labels
为容器添加Docker元数据,为容器添加辅助说明信息:
1 | labels: |
2 | com.jusene.description:"for web" |
links
链接到其他服务的容器,格式(SERVICE:ALIAS)。
1 | links: |
2 | - mysql:db |
3 | - django:web |
4 | - redis |
net
设置网络模式。
1 | net: "none" |
2 | net: "bridge" |
3 | net: "container:[name or id]" |
4 | net: "host" |
pid
根主机系统共享进程命名空间,以及容器和宿主机之间可以通过进程id相互访问。
ports
暴露端口信息,映射端口。
1 | ports: |
2 | - "3000" |
3 | - "8000:8000" |
ulimits
指定容器的ulimits限制值。
1 | ulimits: |
2 | nproc: 65535 |
3 | nfile: |
4 | soft: 20000 |
5 | hard: 40000 |
volumes
设置数据卷。
1 | volumes: |
2 | - /var/lib/mysql |
3 | - cache:/tmp/cache |
volumes_from
从另一个服务或容器挂载它的数据卷。
1 | volumes_from: |
2 | - service_name |
3 | - container_name |
其他指令
1 | - cpu_shares |
2 | 指定cpu的使用率 |
3 | |
4 | - cpuset |
5 | 设置绑定的cpu |
6 | |
7 | - entrypoint |
8 | 指定服务容器启动执行的命令 |
9 | entrypoint: /code/docker-entrypoint.sh |
10 | |
11 | - user |
12 | 指定容器运行应用的用户名 |
13 | |
14 | - working_dir |
15 | 指定容器中的工作目录 |
16 | |
17 | - mem_limit |
18 | 指定内存限制 |
19 | |
20 | - memswap_limit |
21 | 指定swap的限制 |
22 | |
23 | - restart |
24 | 指定容器退出的重启策略,生产环境推荐 always或者unless-stopped |
25 | |
26 | - readonly |
27 | 以只读模式挂载容器的root文件系统,意味不能对容器内容做修改。 |
28 | |
29 | - stdin_open |
30 | 打开标准输入,可以接受外部输入。 |
31 | |
32 | - tty |
33 | 模拟伪终端 |
实例演示
前端负载均衡haproxy轮询访问三台主机
Dockfile
1
FROM python:latest
2
MAINTAINER jusene
3
4
WORKDIR /webapp
5
6
RUN pip install flask
app.py
1
#-*- coding=utf-8 -*-
2
3
from flask import Flask
4
import socket
5
6
app=Flask(__name__)
7
8
@app.route('/')
9
def hello():
10
localip=socket.gethostbyname(socket.gethostname())
11
return "You want to request {0} host!".format(localip)
12
13
if __name__== "__main__":
14
app.run(host='0.0.0.0',debug=True)
haproxy.cfg
1
global
2
log 127.0.0.1 local2
3
defaults
4
mode http
5
log global
6
option httplog
7
option dontlognull
8
option http-server-close
9
option forwardfor except 127.0.0.0/8
10
option redispatch
11
retries 3
12
timeout http-request 10s
13
timeout queue 1m
14
timeout connect 10s
15
timeout client 1m
16
timeout server 1m
17
timeout http-keep-alive 10s
18
timeout check 10s
19
maxconn 3000
20
listen web
21
bind *:80
22
balance roundrobin
23
server web_1 web_1:5000 check
24
server web_2 web_2:5000 check
25
server web_3 web_3:5000 check
26
option httpchk GET /
27
http-check expect status 200
docker-compose.yml
1
web_1:
2
build: ./
3
command: python app.py
4
expose:
5
- 5000
6
volumes:
7
- ./app.py:/webapp/app.py
8
web_2:
9
build: ./
10
command: python app.py
11
expose:
12
- 5000
13
volumes:
14
- ./app.py:/webapp/app.py
15
web_3:
16
build: ./
17
command: python app.py
18
expose:
19
- 5000
20
volumes:
21
- ./app.py:/webapp/app.py
22
23
24
haproxy:
25
image: haproxy:latest
26
volumes:
27
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
28
links:
29
- web_1:web_1
30
- web_2:web_2
31
- web_3:web_3
32
ports:
33
- "80:80"
启动docker-compose编排docker
1 | ~}# docker-compose up |
2 | Starting composehaproxyweb_web_1_1 ... |
3 | Starting composehaproxyweb_web_2_1 ... |
4 | Starting composehaproxyweb_web_1_1 |
5 | Starting composehaproxyweb_web_2_1 |
6 | Starting composehaproxyweb_web_3_1 ... |
7 | Starting composehaproxyweb_web_3_1 ... done |
8 | Starting composehaproxyweb_haproxy_1 ... |
9 | Starting composehaproxyweb_haproxy_1 ... done |
10 | Attaching to composehaproxyweb_web_2_1, composehaproxyweb_web_1_1, composehaproxyweb_web_3_1, composehaproxyweb_haproxy_1 |
11 | haproxy_1 | <7>haproxy-systemd-wrapper: executing /usr/local/sbin/haproxy -p /run/haproxy.pid -f /usr/local/etc/haproxy/haproxy.cfg -Ds |
12 | web_2_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) |
13 | web_2_1 | * Restarting with stat |
14 | web_1_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) |
15 | web_1_1 | * Restarting with stat |
16 | web_3_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) |
17 | web_3_1 | * Restarting with stat |
18 | web_2_1 | * Debugger is active! |
19 | web_2_1 | * Debugger PIN: 170-658-094 |
20 | web_1_1 | * Debugger is active! |
21 | web_1_1 | * Debugger PIN: 133-252-717 |
22 | web_2_1 | 172.17.0.5 - - [23/Aug/2017 20:25:58] "GET / HTTP/1.0" 200 - |
23 | web_3_1 | * Debugger is active! |
24 | web_3_1 | * Debugger PIN: 169-840-183 |
25 | web_3_1 | 172.17.0.5 - - [23/Aug/2017 20:25:58] "GET / HTTP/1.0" 200 - |
26 | web_1_1 | 172.17.0.5 - - [23/Aug/2017 20:25:59] "GET / HTTP/1.0" 200 - |
测试:
1 | [root@INIT ~]# curl 10.211.55.6 |
2 | You want to request 172.17.0.3 host! |
3 | [root@INIT ~]# curl 10.211.55.6 |
4 | You want to request 172.17.0.4 host! |
5 | [root@INIT ~]# curl 10.211.55.6 |
6 | You want to request 172.17.0.2 host! |
7 | [root@INIT ~]# curl 10.211.55.6 |
8 | You want to request 172.17.0.3 host! |
9 | [root@INIT ~]# curl 10.211.55.6 |
10 | You want to request 172.17.0.4 host! |
11 | [root@INIT ~]# |