Jusene's Blog

Docker三剑客之一 Docker Compose

字数统计: 3.5k阅读时长: 15 min
2017/11/13 Share

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搜索域。

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中定义的容器和数据卷容器

链接到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"

链接到其他服务的容器,格式(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 ~]#
CATALOG
  1. 1. Compose
    1. 1.1. Compose的安装
  2. 2. Compose命令说明
  3. 3. Compose环境变量
  4. 4. Compose模板文件
    1. 4.1. build
    2. 4.2. cap_add,cap_drop
    3. 4.3. command
    4. 4.4. container_name
    5. 4.5. devices
    6. 4.6. dns
    7. 4.7. dns_search
    8. 4.8. dockerfile
    9. 4.9. env_file
    10. 4.10. environment
    11. 4.11. expose
    12. 4.12. extends
    13. 4.13. external_links
    14. 4.14. extra_hosts
    15. 4.15. log_driver
    16. 4.16. log_opt
    17. 4.17. images
    18. 4.18. labels
    19. 4.19. links
    20. 4.20. net
    21. 4.21. pid
    22. 4.22. ports
    23. 4.23. ulimits
    24. 4.24. volumes
    25. 4.25. volumes_from
    26. 4.26. 其他指令
  5. 5. 实例演示