一、Docker-Compose介绍
负责实现对Docker容器集群的快速编排。
Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。
Docker-Compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。
Docker-Compose项目由Python编写,调用Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。
二、Docker-Compose安装
安装命令:
apt-get install python-pip
apt-get -y install docker-compose
备注:
(1)红帽系Linux使用以下命令安装
yum -y install python-pip
yum -y install docker-compose
(2)查看安装的版本
docker-compose -v
docker-compose version 1.21.0, build unknown
(3)Docker-compose卸载。
apt-get remove docker-compose
三、Docker-Compose文件配置常用字段及说明
Docker-Compose标准模板文件应该包含version、services、networks 三大部分,最关键的是services和networks两个部分。
举例:
version: '3'
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
Compose目前有三个版本分别为Version 1,Version 2,Version 3,Compose区分Version 1和Version 2(Compose 1.6.0+,Docker Engine 1.10.0+)。Version 2支持更多的指令。Version 1将来会被弃用。
3-1、image
image是指定服务的镜像名称或镜像ID。如果镜像在本地不存在,Compose将会尝试拉取镜像。
services:
web:
image: hello-world
3-2、build
服务除了可以基于指定的镜像,还可以基于一份Dockerfile,在使用up启动时执行构建任务,构建标签是build,可以指定Dockerfile所在文件夹的路径。Compose将会利用Dockerfile自动构建镜像,然后使用镜像启动服务容器。
3-2-1、build下的参数
字段 |
描述说明 | |
build |
直接传值的话是指定包含构建上下文的路径, 或作为一个对象,该对象具有 context 和指定的 dockerfile 文件以及 args 参数值 | |
context |
指定 Dockerfile 文件所在的路径和其需要文件/目录的上下文路径 | |
dockerfile |
指定 context 指定的目录下面的 Dockerfile 的名称(默认为 Dockerfile) | |
args |
Dockerfile 在 build 过程中需要的参数 (等同于 docker container build --build-arg 的作用) | |
cache_from |
v3.2中新增的参数, 指定缓存的镜像列表 (等同于 docker container build --cache_from 的作用) | |
labels |
v3.3中新增的参数, 设置镜像的元数据 (等同于 docker container build --labels 的作用) | |
shm_size |
v3.5中新增的参数, 设置容器 /dev/shm 分区的大小 (等同于 docker container build --shm-size 的作用) |
3-2-2、指定构建路径并在该路径下读取Dokcerfile
(1)示例1:相对路径,只要上下文确定就可以读取到Dockerfile。
build: /path/to/build/dir
(2)示例2:设定上下文根目录,然后以该目录为准指定Dockerfile。
build: ./dir
3-2-3、构建路径与读取Dockerfile的路径区分
build都是一个目录,如果要指定Dockerfile文件需要在build标签的子级标签中使用dockerfile标签指定。
(1)context指定构建路径
(2)dockerfile指定dockerfile文件路径
build:
context: ../
dockerfile: path/of/Dockerfile
备注:
1)如果同时指定image和build两个标签,那么Compose会构建镜像并且把镜像命名为image值指定的名字。
3-3、commond
覆盖容器启动后默认执行的命令, 支持 shell 格式和 [] 格式
command: bundle exec thin -p 3000
3-4、container_name
指定容器的名称 (等同于 docker run --name 的作用)。可以自定义项目名称、服务名称,但如果想完全控制容器的命名,可以使用标签指定:
container_name: app
备注:
1)Compose的容器名称建议格式是:<项目名称><服务名称><序号>
3-5、depends_on
定义容器启动顺序 。用于解决容器的依赖、启动先后的问题。
在使用Compose时,最大的好处就是少打启动命令,但一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。例如在没启动数据库容器的时候启动应用容器,应用容器会因为找不到数据库而退出。
示例:
version: '3'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
上述YAML文件定义的容器会先启动redis和db两个服务,最后才启动web 服务。
备注:
1)此选项解决了容器之间的依赖关系, 此选项在 v3 版本中 使用 swarm 部署时将忽略该选项
3-6、PID
共享宿主机的 进程空间(PID)。将PID模式设置为主机PID模式,跟主机系统共享进程命名空间。容器使用pid标签将能够访问和操纵其他容器和宿主机的名称空间。
pid: "host"
3-7、ports
ports用于映射端口的标签。使用HOST:CONTAINER格式或者只是指定容器的端口,宿主机会随机映射端口。
# 建立宿主机和容器之间的端口映射关系, ports 支持两种语法格式
# SHORT 语法格式示例:
ports
- "3000" # 暴露容器的 3000 端口, 宿主机的端口由 docker 随机映射一个没有被占用的端口
- "3000-3005" # 暴露容器的 3000 到 3005 端口, 宿主机的端口由 docker 随机映射没有被占用的端口
- "8000:8000" # 容器的 8000 端口和宿主机的 8000 端口建立映射关系
- "9090-9091:8080-8081"
- "127.0.0.1:8001:8001" # 指定映射宿主机的指定地址的
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp" # 指定协议
# LONG 语法格式示例:(v3.2 新增的语法格式)
ports:
- target: 80 # 容器端口
published: 8080 # 宿主机端口
protocol: tcp # 协议类型
mode: host # host 在每个节点上发布主机端口, ingress 对于群模式端口进行负载均衡
备注:
1)当使用HOST:CONTAINER格式来映射端口时,如果使用的容器端口小于60可能会得到错误得结果,因为YAML将会解析xx:yy这种数字格式为60进制。所以建议采用字符串格式。
3-8、extra_hosts
添加 host 记录到容器中的 /etc/hosts 中 (等同于 docker run --add-host 的作用)
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
启动后查看容器内部hosts:
162.242.195.82 somehost
50.31.209.229 otherhost
3-9、volumes
定义容器和宿主机的卷映射关系。挂载一个目录或者一个已存在的数据卷容器,可以直接使用 [HOST:CONTAINER]格式,或者使用[HOST:CONTAINER:ro]格式,后者对于容器来说,数据卷是只读的,可以有效保护宿主机的文件系统。
Compose的数据卷指定路径可以是相对路径,使用 . 或者 .. 来指定相对目录。 数据卷的格式可以是下面多种形式
其和 networks 一样可以位于 services 键的二级键(Long语法格式)和 compose 顶级键(short语法格式), 如果需要跨服务间使用则在顶级键定义, 在 services 中引用
# SHORT 语法格式示例:
volumes:
- /var/lib/mysql # 映射容器内的 /var/lib/mysql 到宿主机的一个随机目录中
- /opt/data:/var/lib/mysql # 映射容器内的 /var/lib/mysql 到宿主机的 /opt/data
- ./cache:/tmp/cache # 映射容器内的 /var/lib/mysql 到宿主机 compose 文件所在的位置
- ~/configs:/etc/configs/:ro # 映射容器宿主机的目录到容器中去, 权限只读
- datavolume:/var/lib/mysql # datavolume 为 volumes 已经存在的命名的数据卷, 在此处直接调用
# LONG 语法格式示例:(v3.2 新增的语法格式)
version: "3.2"
services:
web:
image: nginx:alpine
ports:
- "80:80"
volumes:
- type: volume # mount 的类型, 必须是 bind、volume 或 tmpfs
source: datavolume # 宿主机目录
target: /data # 容器目录
volume: # 配置额外的选项, 其 key 必须和 type 的值相同
nocopy: true # volume 额外的选项, 在创建卷时禁用从容器复制数据
- type: bind # volume 模式只指定容器路径即可, 宿主机路径随机生成; bind 需要指定容器和数据机的映射路径
source: ./static
target: /opt/app/static
read_only: true # 设置文件系统为只读文件系统
volumes:
datavolume:
driver: local
备注:
1)bind
挂载类型允许您将宿主机上的文件或目录直接挂载到容器内部。这是通过指定宿主机的路径(source)和容器内的挂载点(target)来实现的。使用bind挂载时,容器内部对挂载点的任何更改都会直接反映到宿主机的文件系统中,反之亦然。
优点:
- 直接访问和修改宿主机的文件或目录。
- 对于需要持久化数据到宿主机的场景很有用。
缺点:
- 可能会增加容器与宿主机之间的耦合度。
- 如果宿主机上的文件或目录被删除,容器中的挂载点也会变得不可用。
示例(在Docker Compose文件中):
volumes:
- type: bind
source: /path/on/host
target: /path/in/container
2)volume
它提供了一种在容器和宿主机之间管理数据的方式,但与bind挂载不同,volume是由Docker管理的,并且具有一些额外的特性和安全性。使用volume时,您可以指定一个卷名称(而不是宿主机的路径),Docker会在其管理的存储中为该卷分配空间。
优点:
- 由Docker管理,更易于迁移和备份。
- 可以在多个容器之间共享。
- 提供了一定的隔离和安全性,因为容器的用户通常不会拥有对宿主机上卷的直接访问权限。
缺点:
- 相对于bind挂载,可能不那么直观,因为您不直接指定宿主机的路径。
示例(在Docker Compose文件中):
volumes:
- datavolume:/path/in/container
# 然后在顶级volumes部分定义datavolume
volumes:
datavolume:
注意:在上面的示例中,第一个volumes键下的条目实际上是在服务定义中指定卷挂载,而第二个volumes键(位于YAML文件的顶层)用于定义自定义卷。但是,如果您只是想要使用Docker管理的匿名卷,而不需要在Docker Compose文件中显式定义它,则可以省略顶层的volumes定义,并直接在服务定义中指定卷名称(Docker会自动创建它)。
3)tmpfs
挂载类型允许您将容器的一个目录挂载为临时文件系统。这意味着挂载到该目录的数据将存储在主机的内存中,而不是写入磁盘。当容器停止时,tmpfs挂载中的数据将被删除。
优点:
- 高性能,因为数据存储在内存中。
- 容器停止时自动清理数据,避免留下垃圾文件。
缺点:
- 数据不是持久的,容器停止后数据将丢失。
- 如果宿主机的内存不足,可能会影响系统性能。
示例(在Docker Compose文件中):
volumes:
- type: tmpfs
target: /path/in/container
tmpfs:
size: 1000000 # 可选,指定tmpfs的大小(以字节为单位)
请注意,tmpfs挂载在Docker Compose文件中可能需要稍微不同的语法,具体取决于Docker Compose的版本和Docker Engine的API版本。上面的示例可能需要根据您使用的具体版本进行调整。在某些版本中,tmpfs挂载可能不是通过tmpfs键直接配置的,而是作为服务定义中的一部分来配置的。
3-10、dns
设置 DNS 地址(等同于 docker run --dns 的作用)。或者说自定义DNS服务器。可以是一个值,也可以是一个列表。
dns:8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
3-11、expose
暴露端口,但不映射到宿主机,只允许能被连接的服务访问( 类似于 Dockerfile 的 EXPOSE 指令)。仅可以指定内部端口为参数,如下所示:
expose:
- "3000"
- "8000"
3-12、links
链接到其它服务中的容器。使用服务名称(同时作为别名),或者服务名称:服务别名(如 SERVICE:ALIAS),例如
links:
- db
- db:database
- redis
备注:
1)该选项是 docker 历史遗留的选项, 目前已被用户自定义网络名称空间取代, 最终有可能被废弃
2)在使用 swarm 部署时将忽略该选项
3-13、network_mode
设置网络模式。
net: "bridge"
net: "none"
net: "host"
3-14、restart
定义容器重启策略。有以下几个值选择:
序号 |
值 |
描述说明 |
1 |
no |
禁止自动重启容器(默认) |
2 |
always |
无论如何容器都会重启 |
3 |
on-failure |
当出现 on-failure 报错时, 容器重新启动 |
备注:
1)在使用 swarm 部署时将忽略该选项, 在 swarm 使用 restart_policy 代替 restart
3-15、env_file
从指定文件中读取变量设置为容器中的环境变量, 可以是单个值或者一个文件列表, 如果多个文件中的变量重名则后面的变量覆盖前面的变量, environment 的值覆盖 env_file 的值
文件格式:
RACK_ENV=development
使用示例:
version: '3'
services:
webapp:
image: my-web-app:latest
env_file:
- .env
# 或者指定多个文件
- ./config/common.env
- ./config/overrides.env
3-16、environment
设置环境变量, environment 的值可以覆盖 env_file 的值 (等同于 docker run --env 的作用)
使用示例:
version: '3'
services:
webapp:
image: my-web-app:latest
environment:
- DB_HOST=localhost
- DB_USER=root
- DB_PASS=secret
3-17、healthcheck
v2.1 以上版本, 定义容器健康状态检查, 类似于 Dockerfile 的 HEALTHCHECK 指令
healthcheck:
# 检查容器检查状态的命令, 该选项必须是一个字符串或者列表, 第一项必须是 NONE, CMD 或 CMD-SHELL, 如果其是一个字符串则相当于 CMD-SHELL 加该字符串
test:["CMD", "curl", "-f", "http://localhost/health"]
interval: 1m30s # 每次检查之间的间隔时间
timeout: 10s # 运行命令的超时时间
retries: 3 # 重试次数
start_period: 40s # v3.4 以上新增的选项, 定义容器启动时间间隔
disable: true # true 或 false, 表示是否禁用健康状态检测和 test: NONE 相同
备注:
1)test内选项第一个参数:
序号 |
第一个选项值 |
描述说明 |
1 |
NONE |
禁用容器的健康状态检测 |
2 |
CMD |
更接近于直接执行命令。 示例test: ["CMD", "curl", "-f", "http://localhost"] |
3 |
CMD-SHELL |
允许你在shell中执行多条命令或使用shell特性(如变量、管道等)。 test: ["CMD-SHELL", "curl -f http://localhost || exit 1"] 或者 test: curl -f https://localhost || exit 1 |