Docker Compose是一款用于定义和运行复杂应用程序的Docker工具。在使用Docker容器的应用中,通常由多个容器组成。使用Docker Compose可以摆脱使用shell脚本来启动容器的繁琐过程。
Compose通过一个配置文件来管理多个Docker容器。在配置文件中,我们使用services来定义所有的容器。然后,使用docker-compose脚本来启动、停止和重启应用,以及与应用中的服务和所有依赖的容器进行交互。这种方式非常适合开发阶段中组合使用多个容器的场景。
常用的Docker Compose文件格式版本和对应的Docker引擎版本。对于较旧的Docker引擎版本,可能不支持较新的Compose文件格式版本。因此,在选择Compose文件格式版本时,请确保与您使用的Docker引擎版本兼容。
Docker Compose文件格式版本 | 对应的Docker引擎版本 |
---|---|
1 | Docker 1.8.0+ |
2 | Docker 1.10.0+ |
2.1 | Docker 1.12.0+ |
2.2 | Docker 1.13.0+ |
3 | Docker 17.06.0+ |
3.1 | Docker 17.12.0+ |
3.2 | Docker 18.02.0+ |
3.3 | Docker 18.06.0+ |
3.4 | Docker 18.09.0+ |
3.5 | Docker 19.03.0+ |
3.6 | Docker 20.10.0+ |
3.7 | Docker 20.10.0+ |
3.8 | Docker 20.10.0+ |
3.9 | Docker 20.10.2+ |
参考:https://docs.docker.com/compose/overview/
从github上下载docker-compose二进制文件安装,可以使用以下命令来下载最新版本的Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
你也可以使用:$ sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-
uname -s
-uname -m
-o /usr/local/bin/docker-compose
授予Docker Compose执行权限。运行以下命令来为Docker Compose设置执行权限:
sudo chmod +x /usr/local/bin/docker-compose
验证安装。运行以下命令来验证Docker Compose是否成功安装:
docker-compose --version
docker-compose version 1.xx.1, build xxxxx
如果成功安装,将显示Docker Compose的版本信息。
$ sudo chmod +x /usr/local/bin/docker-compose
在Compose配置文件中,services部分用来定义所有的容器服务。每个服务都有一个唯一的名称,并包含了需要运行该服务的相关配置信息,包括镜像、端口映射、环境变量等。通过定义services部分,可以轻松地组织和管理复杂的多容器应用程序。
services:
web:
image: java-app
例如下面这些格式都是可以的:
image: redis
image: ubuntu:14.04
image: a4bc65fd
标明image的ID,这个image ID可以是本地也可以是远程的,如果本地不存在,Compose会尝试去pull下来。
除了可以基于指定的镜像启动服务,Compose还提供了基于Dockerfile构建镜像的功能。通过使用build标签,可以指定Dockerfile所在文件夹的路径,Compose将会自动构建镜像并将其用于启动服务容器。
build: /path/to/build/dir: 也可以是相对路径,只要上下文确定就可以读取到Dockerfile。
build: ./dir:设定上下文根目录,然后以该目录为准指定Dockerfile。
dockerfile:制定相对的目录信息控制。
build:
context: ../
dockerfile: path/of/Dockerfile
build构建镜像的方式给予了更大的灵活性,可以根据自己的需求来定制镜像,可以在Dockerfile中定义所需的操作,如安装软件包、配置环境变量等。当使用up命令启动服务时,Compose会自动执行构建任务,生成镜像,并使用该镜像来启动服务容器。
注意:build 都是一个目录,如果你要指定Dockerfile文件需要在build标签的子级标签中使用dockerfile 标签指定,如上面的例子。
如果同时指定了image 和 build 两个标签,那么Compose会构建镜像并且把镜像命名为image后面的那个名字。
build: ./dir
image: appName:tag
既然可以在 docker-compose.yml 中定义构建任务,那么一定少不了 args 这个标签,就像 Dockerfile 中的 ARG 指令,它可以在构建过程中指定环境变量,但是在构建成功后取消,在 docker-compose.yml 文件中也支持这样的写法:
build:
context: .
args:
KEY: VALUE
此外,Dockerfile中也支持一种更易读的ARG指令的写法,尤其适合提高文件的可读性。
build:
context: .
args:
- KEY=1
- VALUE=2
与ENV指令不同,ARG指令允许在构建过程中接受空值,从而可以在构建过程中动态地将值赋予它们。
args:
- KEY
- VALUE
使用ARG指令定义的参数允许为空值。在构建过程中,可以使用–build-arg选项将值赋予该参数,或者在构建命令中使用–build-arg参数指定值。这种特性允许在构建过程中根据需要动态地传递参数值,使得构建过程更加灵活和可配置。
注意:YAML 的布尔值(true, false, yes, no, on, off)必须要使用引号引起来(单引号、双引号均可),否则会当成字符串解析。
在Compose配置文件中,使用command可以覆盖容器启动后默认执行的命令。通过指定command来指定容器启动后要执行的自定义命令。
例如,command: tailf -n 200 xx.log
将容器的默认执行命令替换为tailf -n 200 xx.log
,这表示容器启动后将执行该命令。
注意,command也可以写成类似Dockerfile中的格式,使用一个数组来表示命令及其参数。例如,command: [tailf -n 200 xx.log]与上述的写法效果是一样的。
使用command可以灵活地覆盖和定制容器的启动命令,以满足特定的需求。这使得Compose配置更加灵活,能够适应不同的应用场景。
在使用Compose时,最大的优势之一是减少了启动命令的繁琐性。然而,一般情况下,项目中容器的启动顺序是有一定要求的。直接按照配置文件中的顺序从上到下启动容器可能会导致容器依赖关系的问题,从而引发启动失败的情况。
举例来说,如果在启动应用容器之前未启动数据库容器,应用容器会因为找不到数据库而退出。为了规避这种情况,我们需要引入一个关键标签,即depends_on
。这个标签解决了容器之间的依赖关系和启动顺序的问题。
示例
#指定版本号
version: '2'
#指定网络
networks:
testNetWork
#指定服务
services:
#服务一
test-app:
image: "ts/app:1.0" #从镜像生成
networks: #指定该服务的网络
- testNetWork
depends_on: #指定服务的依赖
- db
ports:
- "8080:8080" # 指定端口的映射
nginx:
build: nginx #指定镜像的构建
networks:
- testNetWork
depends_on:
- test-app
ports:
- "80:80"
db:
image: "mysql"
networks:
- testNetWork
environment: # 指定环境变量
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: testPassword
volumes:
- $PWD/data:/var/lib/mysql
ports:
- "3306:3306"
通过在Compose配置文件中使用depends_on
标签,可以明确指定容器之间的启动顺序。这确保了在启动某个服务之前,所依赖的服务已经成功启动。这种方式有效地解决了容器启动顺序的管理问题,提高了整个应用系统的可靠性。
在Compose配置中,端口信息的暴露是一个重要的配置项。常见的简单格式包括使用"宿主:容器"(HOST主机:CONTAINER容器)格式或者仅仅指定容器的端口(宿主将会随机选择端口)。
这样的端口映射配置允许定义容器与宿主之间的通信端口关系,确保服务能够正确地被访问。通过合理配置端口映射,可以满足不同应用场景下的需求,提高Compose配置的灵活性。
ports:
- "3000"
- "8000:8000"
- "49100:22"
- "127.0.0.1:8001:8001"
“3000”:这表示将容器的端口3000映射到宿主机的随机端口。系统会动态选择一个可用的宿主机端口进行映射。
“8000:8000”:这表示将容器的端口8000映射到宿主机的8000端口。访问宿主机的8000端口将转发到容器的8000端口。
“49100:22”:这表示将容器的22端口(SSH端口)映射到宿主机的49100端口。这是一个非标准的映射,可能用于特定的网络配置。
“127.0.0.1:8001:8001”:这表示将容器的8001端口映射到宿主机的127.0.0.1(本地回环地址)的8001端口。这种配置将使得只能通过宿主机本地访问容器的8001端口。
通过这些映射配置,可以方便地在宿主机与容器之间建立网络连接,实现容器服务的对外访问。这样可以确保容器中运行的服务能够接收来自网络的请求,并将其转发到相应的容器内部端口。
ports:
- "3000-3005"
- "9090-9091:8080-8081"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
“3000-3005”:这表示将容器的端口3000到3005范围内的端口映射到宿主机的随机端口。系统会动态选择一个可用的宿主机端口进行映射。
“9090-9091:8080-8081”:这表示将容器的8080端口映射到宿主机的9090端口,同时将容器的8081端口映射到宿主机的9091端口。这样可以一一对应地映射多个端口。
“127.0.0.1:5000-5010:5000-5010”:这表示将容器的5000到5010范围内的端口映射到宿主机的127.0.0.1地址,对应的端口范围也是5000到5010。这允许在宿主机上通过这个范围的端口访问容器内的服务。
“6060:6060/udp”:这表示将容器的UDP端口6060映射到宿主机的6060端口。UDP是一种无连接的协议,这样的配置适用于需要使用UDP协议的服务。
注意,当使用"HOST:CONTAINER"格式来映射端口时,如果容器端口小于60,可能会导致错误的结果,因为YAML将解析"xx:yy"这种数字格式为60进制。因此,建议采用字符串格式来避免潜在的问题。
在Compose配置中,挂载目录或已存在的数据卷容器可以采用类似 [HOST:CONTAINER] 或 [HOST:CONTAINER:ro] 的格式。后者中的":ro"表示该数据卷对于容器是只读的,从而有效地保护了宿主机文件系统的完整性。
Compose中,数据卷的指定路径可以是相对路径,允许使用 “.” 或 “…” 来指定相对目录,提高配置的灵活性。
数据卷的格式支持多种形式,其中一些可能包括:
[HOST:CONTAINER]
:将宿主机上的路径挂载到容器中的指定路径。
[HOST:CONTAINER:ro]
:将宿主机上的路径以只读方式挂载到容器中的指定路径,以增加对宿主机文件系统的保护。
这样的挂载配置允许容器与宿主机之间共享数据,同时通过只读设置,确保容器无法对挂载的数据进行写操作,从而提高文件系统的安全性。
volumes:
// 只是指定一个路径,Docker会自动在创建一个数据卷(这个路径是容器内部的)。
- /var/lib/mysql
// 使用绝对路径挂载数据卷
- /opt/data:/var/lib/mysql
// 以Compose配置文件为中心的相对路径作为数据卷挂载到容器。
- ./cache:/tmp/cache
// 使用用户的相对路径(~/ 表示的目录是 /home/<用户目录>/ 或者 /root/)。
- ~/configs:/etc/configs/:ro
// 已经存在的命名的数据卷。
- datavolume:/var/lib/mysql
如果你不使用宿主机的路径,你可以指定一个volume_driver。
volume_driver: mydriver
在Compose配置中,您可以通过两种形式(数组或字典)来添加环境变量。请注意以下建议的优化和润色:
使用数组或字典形式:可以使用数组或字典来定义环境变量。数组形式适用于单个键-值对,而字典形式适用于多个键-值对。例如:
数组形式:
environment:
- KEY1=value1
- KEY2=value2
字典形式:
environment:
KEY1: value1
KEY2: value2
引号括起布尔值:对于布尔类型的变量(如true
,false
,yes
,no
),为确保不被YML解析器转换为True或False,建议用引号括起来。例如:
environment:
- BOOL_VAR="true"
- OTHER_VAR="no"
这样可以确保布尔值在解析时保持不变。
只指定变量名:如果只给出变量名而没有指定具体的值,则Compose会自动获取该变量在主机上的值。这种方式可以用来防止不必要的敏感数据泄露。例如:
environment:
- USERNAME
- PASSWORD
在运行时,Compose会自动获取主机上对应环境变量的值,并将其注入到容
注意:如果你的服务指定了build选项,那么在构建过程中通过environment定义的环境变量将不会起作用。 将使用build的args子选项来定义构建时的环境变量。
命令 | 用途 |
---|---|
build [serviceName] | 进行组合构建 [单个服务] |
up [-d] | 创建并且启动容器 [后台启动] |
start [serviceName] | 启动容器 |
stop [serviceName] | 停止所有服务 [单个服务] |
restart [serviceName] | 重启所有服务 [单个服务] |
rm [serviceName] | 删除容器中的所有容器 [单个服务] |
logs [serviceName] | 观察所有容器的日志 [单个服务] |
ps [serviceName] | 列出相关的容器状态 [单个服务] |
docker-compose up -d
注:使用命令docker-compose ps查看运行状况
一份标准的Compose配置文件应该包含三个主要部分:version、services和networks。其中,最关键的是services和networks两个部分。接下来,让我们先来了解一下services部分的书写规则。
version: '2'
services:
web:
image: dockercloud/hello-world
ports:
- 8080
networks:
- front-tier
- back-tier
redis:
image: redis
links:
- web
networks:
- back-tier
lb:
image: dockercloud/haproxy
ports:
- 80:80
links:
- web
networks:
- front-tier
- back-tier
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
front-tier:
driver: bridge
back-tier:
driver: bridge
除了基本的服务配置外,您还可以使用其他功能,如依赖关系、扩展性配置、容器间通信等,来满足具体应用的需求。