参考文献

安装

  • 通过https://github.com/docker/compose/releases下载docker-compose二进制文件

  • 下载完成后手动上传到linux指定目录/usr/local/bin,将其文件名修改成docker-compose.然后给其加上可执行权限

    1
    2
    # 因为下载后的docker-compose文件是一个可执行脚本,所以要开放其权限
    chmod +x /usr/local/bin/docker-compose
  • 创建软链

    1
    $ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Docker Compose

  • Docker Compose 的前身是 Orchard 公司开发的 Fig,2014 年 Docker 收购了 Orchard 公司,然后将 Fig 重命名为 Docker Compose.现阶段 Docker Compose 是 Docker 官方的单机多容器管理系统,它本质是一个 Python 脚本,它通过解析用户编写的 yaml 文件,调用 Docker API 实现动态的创建和管理多个容器.

Docker Compose模版文件

  • 在使用 Docker Compose 启动容器时, Docker Compose 会默认使用 docker-compose.yml 文件, docker-compose.yml 文件的格式为 yaml(类似于 json,一种标记语言).

  • Docker Compose 模板文件一共有三个版本: v1、v2 和 v3.目前最新的版本为 v3,也是功能最全面的一个版本,下面主要围绕 v3 版本介绍一下如何编写 Docker Compose 文件.

  • Docker Compose 文件主要分为三部分: services(服务)、networks(网络) 和 volumes(数据卷).

    • services(服务):服务定义了容器启动的各项配置,就像我们执行docker run命令时传递的容器启动的参数一样,指定了容器应该如何启动,例如容器的启动参数,容器的镜像和环境变量等.

    • networks(网络):网络定义了容器的网络配置,就像我们执行docker network create命令创建网络配置一样.

    • volumes(数据卷):数据卷定义了容器的卷配置,就像我们执行docker volume create命令创建数据卷一样.

services常用配置

  • build: 用于构建 Docker 镜像,类似于docker build命令,build 可以指定 Dockerfile 文件路径,然后根据 Dockerfile 命令来构建文件.使用方法如下:

    1
    2
    3
    4
    5
    build:
    ## 构建执行的上下文目录
    context: .
    ## Dockerfile 名称
    dockerfile: Dockerfile-name
  • command: 用于覆盖容器默认的启动命令,它和 Dockerfile 中的 CMD 用法类似,也有两种使用方式:

    1
    2
    3
    command: sleep 3000

    command: ["sleep", "3000"]
  • container_name: 用于指定容器启动时容器的名称.使用格式如下:

    1
    container_name: nginx
  • depends_on: 用于指定服务间的依赖关系,这样可以先启动被依赖的服务.例如,我们的服务依赖数据库服务 db,可以指定 depends_on 为 db.使用格式如下:

    1
    2
    3
    4
    5
    6
    7
    8
    version: "3.8"
    services:
    my-web:
    build: .
    depends_on:
    - db
    db:
    image: mysql
    • 长语法

      • restart:当trueCompose 实现必须在更新依赖服务后重新启动此服务时.这适用于由 Compose 操作控制的显式重启,不包括容器运行时在容器死亡后自动重启.

      • condition: 满足依赖性的条件

        • service_started: 等同于上面描述的短语法
        • service_healthy: 指定在启动依赖服务之前依赖项应该是“健康的”
        • service_completed_successfully: 指定在启动依赖服务之前,依赖项应该运行到成功完成
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      services:
      web:
      build: .
      depends_on:
      db:
      condition: service_healthy
      restart: true
      redis:
      condition: service_started
      redis:
      image: redis
      db:
      image: postgres
  • devices: 挂载主机的设备到容器中.使用格式如下:

    1
    2
    devices:
    - "/dev/sba:/dev/sda"
  • s: 自定义容器中的 s 配置.

    1
    2
    3
    s:
    - 8.8.8.8
    - 114.114.114.114
  • s_search: 配置 s 的搜索域.

    1
    2
    3
    s_search:
    - svc.cluster.com
    - svc1.cluster.com
  • entrypoint: 覆盖容器的entrypoint命令.

    1
    2
    3
    entrypoint: sleep 3000

    entrypoint: ["sleep", "3000"]
  • env_file: 指定容器的环境变量文件,启动时会把该文件中的环境变量值注入容器中.

    1
    2
    env_file:
    - ./dbs.env
    • env 文件的内容格式如下:KEY_ENV=values
  • environment: 指定容器启动时的环境变量.

    1
    2
    environment:
    - KEY_ENV=values
  • image: 指定容器镜像的地址.

    1
    image: busybox:latest
  • pid: 共享主机的进程命名空间,像在主机上直接启动进程一样,可以看到主机的进程信息.

    1
    pid: "host"
  • ports: 暴露端口信息,使用格式为 HOST:CONTAINER,前面填写要映射到主机上的端口,后面填写对应的容器内的端口.

    • 端口映射不得与一起使用network_mode: host,这样做会导致运行时错误.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ports:
    - "1000"
    - "1000-1005"
    - "8080:8080"
    - "8888-8890:8888-8890"
    - "2222:22"
    - "127.0.0.1:9999:9999"
    - "127.0.0.1:3000-3005:3000-3005"
    - "6789:6789/udp"
  • healthcheck: healthcheck声明运行的检查以确定此服务的容器是否“健康”

    1
    2
    3
    4
    5
    6
    healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost"]
    interval: 1m30s
    timeout: 10s
    retries: 3
    start_period: 40s
  • links: links定义到另一个服务中容器的网络链接.要么指定服务名称和链接别名() SERVICE:ALIAS),要么只指定服务名称

    1
    2
    3
    4
    5
    web:
    links:
    - db
    - db:database
    - redis
    • 链接服务的容器必须可以通过与别名相同的主机名访问,或者如果没有指定别名则为服务名称.
  • network_mode: 设置服务容器网络模式

    • none禁用所有容器网络
    • host这使容器可以原始访问主机的网络接口
      • host模式可以用于所有应用和中间件部署在同一台机器的情况下,应用在容器中连接中间件只需指定ip为localhost即可,因为此时localhost就是代表了宿主机
    • service:{name}这使容器只能访问指定的服务
    1
    2
    3
    network_mode: "host"
    network_mode: "none"
    network_mode: "service:[service name]"
  • restart: 定义平台将应用于容器终止的策略

    • no:默认重启策略.在任何情况下都不会重新启动容器.
    • always:该策略总是重新启动容器,直到它被删除.
    • on-failure:如果退出代码指示错误,该策略将重新启动容器.
    • unless-stopped:无论退出代码如何,该策略都会重新启动容器,但会在服务停止或删除时停止重新启动.
  • networks 这是服务要使用的网络名称,对应顶级的 networks 中的配置.

    1
    2
    3
    4
    5
    6
    7
    8
    services:
    my-service:
    networks:
    - hello-network
    - hello1-network
    networks:
    hello-network: # 定义网络.定义后才能在上面使用,否则报错
    hello1-network: # 定义网络.定义后才能在上面使用,否则报错
  • volumes: 不仅可以挂载主机数据卷到容器中,也可以直接挂载主机的目录到容器中,使用方式类似于使用docker run启动容器时添加 -v 参数.

    1
    2
    3
    4
    5
    6
    7
    8
    version: "3"
    services:
    db:
    image: mysql:5.6
    volumes:
    - type: volume
    source: /var/lib/mysql
    target: /var/lib/mysql
    • volumes 除了上面介绍的长语法外,还支持短语法的书写方式,例如上面的写法可以精简为:
    1
    2
    3
    4
    5
    6
    version: "3"
    services:
    db:
    image: mysql:5.6
    volumes:
    - /var/lib/mysql:/var/lib/mysql
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    version: "3"
    services:
    db:
    image: mysql:5.6
    volumes:
    - mysql_data:/var/lib/mysql

    volumes:
    mysql_data: # 声明上面所使用的数据卷
    # 使用外部已存在的数据卷mysql_data,该数据卷必须存在,不存在的话必须先手动创建,否则报错
    external: true

networks

默认网络

  • 例如, 假设有一个项目,目录名myapp, docker-compose.yml 配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    version: "3"
    services:
    web:
    build: .
    ports:
    - "8000:8000"
    db:
    image: mysql
    ports:
    - "13306:3306"
    • 当执行docker-compose up 的时候.会发生以下事情:
      1. **会创建一个名字是 **myapp_default的网络(networks)
      2. web这个容器会加入到 myapp_default网络中,并且在网络中的名称为:web .
      3. db这个容器会加入到 myapp_default网络中,并且在网络中的名称为:db.

自定义网络

  • 可能通过一级配置networks来自定义网络,可以创建更复杂的网络选项和配置,也可以用来连接已经存在的网络(不是通过compose创建的,如docker network create custom_net)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    services:
    proxy:
    build: ./proxy
    networks:
    - frontend
    app:
    build: ./app
    networks:
    - frontend
    - backend
    db:
    image: postgres
    networks:
    - backend

    networks:
    frontend:
    # Use a custom driver
    driver: custom-driver-1
    backend:
    # Use a custom driver which takes special options
    driver: custom-driver-2
    driver_opts:
    foo: "1"
    bar: "2"

指定一个已经存在的网络

  • 多个容器,不在相同的配置中,也会有网络通讯的需求 .那么就可以使用公共的网络配置.

  • 容器可以加入到已经存在的网络.

    1
    2
    3
    4
    5
    6
    services:
    # ...
    networks:
    network1:
    name: my-pre-existing-network
    external: true

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
version: '3.5'
services:
nginx:
container_name: 'nginx'
image: nginx:1.17.0-alpine
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
volumes:
- /home/tech/conf/nginx.conf:/etc/nginx/nginx.conf
- /home/tech/dcm:/usr/share/nginx/html/imaging
- /var/log/nginx:/var/log/nginx
ports:
- 80:80
- 443:443
networks:
demo:
aliases:
- cloud-suat.nginx

consul:
container_name: 'consul'
image: consul
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
volumes:
- consul-data:/consul/data
- consul-config:/consul/config
ports:
- 8300:8300
- 8301:8301
- 8301:8301/udp
- 8302:8302
- 8302:8302/udp
- 8400:8400
- 8500:8500
command: agent -server -data-dir=/consul/data -config-dir=/consul/config -bind=0.0.0.0 -client=0.0.0.0 -node=consul -bootstrap-expect=1 -ui
networks:
demo:
aliases:
- cloud-suat.consul

mysql:
container_name: 'mysql'
image: mysql:latest
command: --default-authentication-plugin=mysql_native_password
ports:
- "3306:3306"
environment:
- TZ=Asia/Shanghai
- MYSQL_ROOT_PASSWORD=Passw0rd
volumes:
- static-mysql:/var/lib/mysql
networks:
demo:
aliases:
- cloud-suat.mysql
mongo:
container_name: 'mongo'
image: mongo:4.1.13-bionic
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
- MONGO_INITDB_ROOT_USERNAME=mongo
- MONGO_INITDB_ROOT_PASSWORD=mongostorage
volumes:
- mongo-config:/data/configdb
- mongo-storage:/data/db
networks:
demo:
aliases:
- cloud-suat.mongo

minio:
container_name: 'minio'
image: minio/minio:RELEASE.2019-06-19T18-24-42Z
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
- MINIO_ACCESS_KEY=minio
- MINIO_SECRET_KEY=miniostorage
volumes:
- minio-storage:/data
ports:
- 9000:9000
command: server /data
networks:
demo:
aliases:
- cloud-suat.minio
redis:
container_name: 'redis'
image: redis
ports:
- 6379:6379
volumes:
- redis-data:/data/
networks:
demo:
aliases:
- cloud-suat.redis

es:
image: docker.elastic.co/elasticsearch/elasticsearch:7.4.0
container_name: es
environment:
- bootstrap.memory_lock=true
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- discovery.type=single-node
- ELASTIC_PASSWORD=zaq12WSXcde3

ulimits:
memlock:
soft: -1
hard: -1
volumes:
- es-data:/usr/share/elasticsearch/data
ports:
- 9200:9200
- 9300:9300
networks:
demo:
aliases:
- cloud-suat.es

rabbitmq:
container_name: 'rabbitmq'
hostname: 'tech-rabbitmq'
image: rabbitmq:3.7-management-alpine
restart: unless-stopped
environment:
- TZ=Asia/Shanghai
- RABBITMQ_DEFAULT_USER=alice
- RABBITMQ_DEFAULT_PASS=wonderland
volumes:
- rabbitmq-storage:/var/lib/rabbitmq
ports:
- 5672:5672
- 15672:15672
networks:
demo:
aliases:
- cloud-suat.rabbitmq


volumes:
static-files:
name: static-files
rabbitmq-storage:
name: rabbitmq-storage
mongo-config:
name: mongo-config
mongo-storage:
name: mongo-storage
minio-storage:
name: minio-storage
es-data:
name: es-data
consul-data:
name: consul-data
consul-config:
name: consul-config
redis-data:
name: redis-data
static-mysql:
name: static-mysql

networks:
demo:
name: demo


使用GPU

  • 命令行: docker run --rm --gpus all nvidia/cuda nvidia-smi

  • docker-compose.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    version: '2.3'

    services:
    nvsmi:
    image: ubuntu:16.04
    runtime: nvidia
    environment:
    - NVIDIA_VISIBLE_DEVICES=all
    command: nvidia-smi
    • NVIDIA 容器运行时使用容器映像中的环境变量来指定 GPU 加速容器.
      1. NVIDIA_VISIBLE_DEVICES : controls which GPUs will be accessible inside the container. By default, all GPUs are accessible to the container.
      2. NVIDIA_DRIVER_CAPABILITIES : controls which driver features (e.g. compute, graphics) are exposed to the container.
      3. NVIDIA_REQUIRE_* : a logical expression to define the constraints (e.g. minimum CUDA, driver or compute capability) on the configurations supported by the container.

Docker Compose操作命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
docker-compose [-f <arg>...] [options] [--] [COMMAND] [ARGS...]

其中 options 是 docker-compose 的参数,支持的参数和功能说明如下:
  -f, --file FILE             指定 docker-compose 文件,默认为 docker-compose.yml
  -p, --project-name NAME     指定项目名称,默认使用当前目录名称作为项目名称
  --verbose                   输出调试信息
  --log-level LEVEL           日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)
  -v, --version               输出当前版本并退出
  -H, --host HOST             指定要连接的 Docker 地址
  --tls                       启用 TLS 认证
  --tlscacert CA_PATH         TLS CA 证书路径
  --tlscert CLIENT_CERT_PATH  TLS 公钥证书问价
  --tlskey TLS_KEY_PATH       TLS 私钥证书文件
  --tlsverify                 使用 TLS 校验对端
  --skip-hostname-check       不校验主机名
  --project-directory PATH    指定工作目录,默认是 Compose 文件所在路径.

COMMAND 为 docker-compose 支持的命令.支持的命令如下:
  build              构建服务
  config             校验和查看 Compose 文件
  create             创建服务
  down               停止服务,并且删除相关资源
  events             实时监控容器的时间信息
  exec               在一个运行的容器中运行指定命令
  help               获取帮助
  images             列出镜像
  kill               杀死容器
  logs               查看容器输出
  pause              暂停容器
  port               打印容器端口所映射出的公共端口
  ps                 列出项目中的容器列表
  pull               拉取服务中的所有镜像
  push               推送服务中的所有镜像
  restart            重启服务
  rm                 删除项目中已经停止的容器
  run                在指定服务上运行一个命令
  scale              设置服务运行的容器个数
  start              启动服务
  stop               停止服务
  top                限制服务中正在运行中的进程信息
  unpause            恢复暂停的容器
  up                 创建并且启动服务
  version            打印版本信息并退出

Dockerdocker-compose版本关系

Compose file format Docker Engine release
Compose specification 19.03.0+
3.8 19.03.0+
3.7 18.06.0+
3.6 18.02.0+
3.5 17.12.0+
3.4 17.09.0+
3.3 17.06.0+
3.2 17.04.0+
3.1 1.13.1+
3.0 1.13.0+
2.4 17.12.0+
2.3 17.06.0+
2.2 1.13.0+
2.1 1.12.0+
2.0 1.10.0+