容器技术—docker compose
在微服务架构下,我们后端会有许许多多的服务,这些服务之间可能会存在一定的依赖关系,或者会依赖一些第三方的应用容器,在生产环境中我们不可能通过docker命令一个一个地拉取镜像、启动容器,那样做将是一件非常费时费力的事情。想象一下,当我们有几十上百个甚至几百个服务时,需要一个一个的启动,那样子重复性的工作简直让人奔溃。这里介绍一下docker compose,它能够在一定程度上解决上述的困境。Com
容器技术—docker compose
- docker compose
- 1. docker compose安装
- 2. 编排文件
- 3. docker compose常用命令
- 3.1 docker compose [OPTIONS] config [ARGS] [SERVICES]
- 3.2 docker compose [OPTIONS] up [ARGS] [SERVICES]
- 3.3 docker compose [OPTIONS] down [ARGS] [SERVICES]
- 3.4 docker compose [OPTIONS] ps [ARGS] [SERVICES]
- 3.5 docker compose [OPTIONS] exec [ARGS] [SERVICES] [COMMOND][COMMONDARGS]
- 3.6 docker compose [OPTIONS] start [SERVICES]
- 3.7 docker compose [OPTIONS] stop [SERVICES]
- 3.8 docker compose[OPTIONS] restart [ARGS][SERVICES]
- 3.9 docker compose [OPTIONS] pause [SERVICES]
- 3.10 docker compose [OPTIONS] unpause [SERVICES]
- 3.11 docker compose [OPTIONS] kill [ARGS] [SERVICES]
- 3.12 docker compose [OPTIONS] rm [ARGS] [SERVICES]
- 3.13 docker compose [OPTIONS] cp [ARGS]
- 3.14 docker compose [OPTIONS] events [ARGS] [SERVICES]
- 3.15 docker compose [OPTIONS] logs [ARGS] [SERVICES]
- 3.16 docker compose [OPTIONS] top [SERVICES]
- 3.17 docker compose [OPTIONS] top [ARGS] SERVICE PRIVATE_PORT
docker compose
在微服务架构下,我们后端会有许许多多的服务,这些服务之间可能会存在一定的依赖关系,或者会依赖一些第三方的应用容器,在生产环境中我们不可能通过docker命令一个一个地拉取镜像、启动容器,那样做将是一件非常费时费力的事情。想象一下,当我们有几十上百个甚至几百个服务时,需要一个一个的启动,那样子重复性的工作简直让人奔溃。
这里介绍一下docker compose,它能够在一定程度上解决上述的困境。Compose 项目是 Docker 官方的开源项目,是用于定义和运行多容器 Docker 应用程序的工具,负责实现对 Docker 容器集群的快速编排。通过 Compose,可以使用 YML 文件来定义一组相关联的应用容器为一个项目(project)。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。compose实现的快速编排使我们能够站在项目角度将一组相关联容器整合在一起,对这组容器按照指定顺序进行启动,也让项目使用到的容器组合更加清晰,方便不同服务器之间的迁移部署。
Docker compose有2个重要的概念:
- 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
- 项目(project):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。
Compose 的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。
Compose 项目实现上调用了Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持 Docker APl,就可以在其上利用Compose来进行编排管理。
1. docker compose安装
Linux 平台下需要独立安装docker-compose,而windows、mac平台的docker desktop在安装时会一起安装上docker-compose。目前docker compose稳定版本为v2.5.0
,以下示例都是基于此版本,很多博友写的教程都是基于用python编写的v1版本,和最新版本是稍有不同的。
V2版本docker compose是以插件的方式作为docker的一部分的,如果按照官网或者我之前的教程去执行的话,其实已经将docker compose安装上了,如果确实没有安装docker compose,现在官方提供了三种安装方式,分别是快捷安装、存储库安装和二进制文件安装。
1.1 快捷安装
yum install docker-compose-plugin
安装了V2版本的docker compose之后,compose命令被集成到docker平台,作为docker CLI的一部分。之后使用compose命令就不是再用docker-compose了,而是docker compose,中间用空格隔开
验证版本:
docker compose version
1.2 存储库安装
这种安装方式是通过apt-get安装的,apt-get是Debian系列linux操作系统的包管理工作,我习惯使用CentOS,这种方式有点鸡肋。这里就不细讲了。有兴趣的请参考官方文档: https://docs.docker.com/compose/install/
1.3 二进制文件安装
通过以下命令下载docker compose二进制文件:
curl -SL https://github.com/docker/compose/releases/download/<version>/docker-compose-linux-x86_64 -o <安装目录>
如:
mkdir -p /usr/local/lib/docker/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
如果github访问太慢,可以用daocloud下载
curl -SL https://get.daocloud.io/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
修改二进制文件权限:
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
之后通过docker compose命令测试是否安装成功
卸载docker compose
rm /usr/local/lib/docker/cli-plugins/docker-compose
如果你确实习惯使用docker-compose命令开头,在通过二进制文件安装的情况下可以通过创建软链接的方式继续使用这个命令
sudo ln -s /usr/local/lib/docker/cli-plugins/docker-compose /usr/bin/docker-compose
2. 编排文件
编排文件是使用 Docker Compose 的核心,支持compose.yaml或者compose.yml作为默认名称,也向后兼容docker-compose.yaml和docker-compose.yml,如果这些文件都存在则首选compose.yaml。你也可以使用其他名称,只是需要在启动的时候指定文件名。基本格式如下:
services:
frontend:
image: awesome/webapp
ports:
- "443:8043"
networks:
- front-tier
- back-tier
configs:
- httpd-config
secrets:
- server-certificate
backend:
image: awesome/database
volumes:
- db-data:/etc/data
networks:
- back-tier
volumes:
db-data:
driver: flocker
driver_opts:
size: "10GiB"
configs:
httpd-config:
external: true
secrets:
server-certificate:
external: true
networks:
# The presence of these objects is sufficient to define them
front-tier: {}
back-tier: {}
一个 docker-compose.yml 文件的顶层元素有:version、name、service、networks、volumes、configs、secrests,涉及的配置非常多,这里只是稍微讲一下一些比较常用的。
2.1 version
version: "3.9"
version 元素是编排文件的格式版本,而非Docker Compose 或 Docker 引擎的版本号。在新的编排规范中已经被弃用了,新的编排规范主张不应该通过version来选择验证编排文件的架构,而是应该有compose验证是否能够完全解析编排文件,不能的话给出警告。新的编排文件仍然可以写version,这是为了向下兼容,以便在其他版本的compose也可以使用,如果写了则一定要在第一行。Compose文件格式版本主要有1, 2, 2.x, and 3.x,最新版本为3.9,下面的图为官网的版本对照图。
2.2 name
name元素定义编排项目的名称,可以在compose命令启动项目进行覆盖,如果没有定义name元素,则compose会生成默认的name,默认名称为compose。name元素最终会作为编码文件中的一个变量,变量名为COMPOSE_PROJECT_NAME,我们可以在编排文件中以环境变量或者插值的方式使用它。
默认名称:
指定name:
2.3 services
services元素用于定义不同的应用服务,在编排文件中是必需的,是我们定义容器怎么启动编排、怎么依赖的地方。
基本结构如下:
services:
servicename: # 服务名称
# 容器构建配置
image: customimage
服务容器构建配置包含以下一些常用指令:
2.3.1 build
build元素声明怎么通过源代码从本地创建一个镜像。
可以将build指定为定义上下文路径的单个字符串,这个路径字符串以是绝对路径或者相对路径的方式指向Dockerfile文件或者Dockerfile所在的文件夹,不推荐使用绝对路径,因为这样会影响编排文件的可移植性。
services:
serviceA:
build: ../webapp
也可以指定为详细的build定义,常用的build定义指令如下:
services:
serviceB:
build:
context: ../../backend # 上下文路径,相对于compose.yaml
dockerfile: ./service.dockerfile # Dockerfile文件路径,相对于context,这种方式可以指定dockerfile文件名
args:
type:cdc3b19 #添加构建参数,构造参数必须是Dockerfile已经定义的
labels:
description: "service B" #设置构建镜像的标签。
target: publish # 多层构建,可以指定构建哪一层
args和labels可以用字典或数组两种方式进行传参,数组方式如下:
args:
- "type=cdc3b19" #添加构建参数,构造参数必须是Dockerfile已经定义的
labels:
- "description=service B" #设置构建镜像的标签。
target: publish # 多层构建,可以指定构建哪一层
2.3.2 image
指定构建容器使用的镜像,如果本地镜像不存在,则会根据pull_policy配置拉取镜像,相当于 docker run images。
当存在build指令时,image指令可以省略,如果build和image同时存在,build优先,build构建的镜像将使用image指定的名字和标记对其进行标记。
通过本地Dockerfile构建镜像,并通过image设置镜像标签
2.3.3 pull_policy
编码文件拉取镜像的策略。可用值如下:
- always: 从仓库拉取,不使用本地缓存
- never:只是要本地缓存,不从仓库拉取,如果本地没有镜像则报错
- missing: 优先使用本地,如果没有则从此仓库拉取,这是默认值。这个值等同于if_not_present以向下兼容。
- build:从本地源码构建,就算镜像已经存在也会重新构建
如果pull_policy与build同时存在,build优先。
2.3.4 environment
设置环境变量,相当于 docker run -e,可以使用数组或者字典两个格式。
services:
mysql:
image: mysql:5.7
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root #字典格式
或者
services:
mysql:
image: mysql:5.7
ports:
- "3306:3306"
environment:
- "MYSQL_ROOT_PASSWORD=root" #数组格式
- "SESSION_SECRET"
只给定名称的变量会自动获取运行 Compose 主机上对应环境变量的值,如上面的SESSION_SECRET,可以用来防止泄露不必要的数据。
2.3.5 env_file
从文件添加环境变量。可以是单个值或列表的多个值。
env_file: .env
也可以是列表格式:
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
如果通过 docker-compose -f FILE 方式来指定 Compose 模板文件,则 env_file 中变量的路径会基于模板文件路径。
如果有变量名称与 environment 指令冲突,则按照惯例,以 environment 为准。
环境变量文件中每一行必须符合格式,如下,支持 # 开头的注释行。
MYSQL_ROOT_PASSWORD=root
环境变量文件 .env:推荐使用这种命名,因为在Linux下,这种方式命名的文件属于隐藏文件,一定程度上防止泄露不必要的数据。
2.3.6 command
覆盖容器启动的默认命令,可以以两种形式定义:
command: bundle exec thin -p 3000
command: [ "bundle", "exec", "thin", "-p", "3000" ]
以下面的Dockerfile文件为例,容器启动后执行的是 dotnet dockerSample.dll --urls=“http://localhost:80”
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
COPY . .
ENTRYPOINT ["dotnet", "dockerSample.dll", "--urls"]
CMD ["http://localhost:80"]
如果我们想要容器启动后执行的是 dotnet dockerSample.dll --urls=http://0.0.0.0:80,在compose.yaml文件中使用指令 command: [“http://0.0.0.0:80”]
services:
webapp:
build:
context: ./dir #定Dockerfile的上下文目录为当前目录的dir目录下
dockerfile: Dockerfile-alternate
args:
buildno: 1
command: ["http://0.0.0.0:8000"]
2.3.7 entrypoint
覆盖容器启动的默认entrypoint,如果编码文件同时存在command,command将作为entrypoint的参数,可以以字典或者数组的方式定义:
entrypoint: /code/entrypoint.sh
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
- -d
- memory_limit=-1
- vendor/bin/phpunit
还是上面Command指令中的Dockerfile,如果我们想要容器启动后以另一个dll启动,如执行 dotnet dockerSample1.dll --urls=http://0.0.0.0:8000,则在compose.yaml中使用以下指令:
version: '3.9'
services:
webapp:
build:
context: ./dir #定Dockerfile的上下文目录为当前目录的dir目录下
dockerfile: Dockerfile-alternate
args:
buildno: 1
entrypoint:
- dotnet
- dockerSample1.dll
- urls
command: ["http://0.0.0.0:8000"]
2.3.8 depends_on
配置服务依赖关系,当前服务启动时会先启动被依赖的服务,必须等到被依赖的服务进行"ready"状态,当前服务才会启动,当前服务停止后被依赖的服务才会停止。可以以短语法和长语法两种方式书写。
短语法:
services:
web:
build: .
depends_on:
-db
-redis
redis:
image: redis
db:
image: postgres
长语法:
services:
web:
build: .
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
redis:
image: redis
db:
image: postgres
长格式语法允许配置短格式中无法表示的其他字段,主要有condition字段,用于设置服务依赖条件,可用值有以下三个:
- service_started:被依赖服务必须先于依赖服务启动,等同于短语法
- service_healthy:被依赖服务必须达到健康状态检查是健康状态,依赖服务才启动。
- service_completed_successfully:被依赖服务必须达到运行成功,依赖服务才启动。
2.3.9 network_mode
设置网络模式。这里的可用值是特定于平台的,但是定义了特定的值,如果平台支持,这些值必须按以下实现:
- none 禁用所有容器网络
- host 它使容器可以原始访问主机的网络接口
- service:{name} 它只允许容器访问指定的服务
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
2.3.10 networks
配置容器连接的网络,需要引用顶级 networks 下的条目,同一网络上的其他容器可以使用服务名称来连接到对应容器的服务,也可以设置别名,通过别名来连接。
services:
some-service:
networks:
-some-network
-other-network
networks:
some-network:
other-network:
或者
services:
some-service:
networks:
some-network:
aliases:
- alias1
- alias3
other-network:
aliases:
-alias2
networks:
some-network:
other-network:
networks指令下还有诸如ipv4_address, ipv6_address、link_local_ips、priority等参数,大家自行了解,这里就不细讲了。
2.3.11 ports
配置端口映射,需要注意的是,ports不能在network_mode指令设置为host的时候使用。ports指令支持短语法和长语法。
短语法:
[HOST:]CONTAINER[/PROTOCOL]
ports:
-"3000" # 只指定容器端口,宿主机随机选择端口
-"3000-3005" # 指定容器一个范围的端口,宿主机也将选择一个个数相等的端口范围
-"8000:8000" # 指定宿主机端口映射到容器端口,前面的是宿主机
-"9090-9091:8080-8081"# 指定宿主机一个范围的端口映射到容器端口,前面是宿主机
-"49100:22"
-"127.0.0.1:8001:8001" # 指定宿主机ip,如果平台不支持主机ip映射时,编排将失败报错
-"127.0.0.1:5000-5010:5000-5010"
-"6060:6060/udp" # 将端口限制为指定的协议,可用值为tcp、udp
需要注意的是,当使用短语法来映射端口时,如果你使用的容器端口小于 60 你可能会得到错误得结果,因为 YAML 将会解析 xx:yy 这种数字格式为 60 进制。所以建议采用字符串格式。
长语法:
长格式语法允许配置短格式中无法表示的其他字段,如下:
ports:
- target: 80
host_ip: 127.0.0.1
published: 8080
protocol: tcp
mode: host
- target: 80
host_ip: 127.0.0.1
published: 8000-9000
protocol: tcp
mode: host
- target:容器内的端口
- host_ip:主机IP映射,未指定表示所有网络接口( 0.0.0.0 )
- published:物理主机的端口
- protocol:端口协议(tcp或udp)
- mode:host 和ingress 两种模式,host用于在每个节点上发布主机端口,ingress 用于被负载平衡的swarm模式端口。
2.3.12 links
链接到另一个服务中的容器。 需要指定服务名称,也可以设置别名。
web:
links:
- db
- db:database
- redis
在当前的web服务的容器中可以通过链接的db服务的别名database访问db容器中的数据库应用,如果没有指定别名,则可直接使用服务名访问。
服务进行通信不需要通过连接来启用 - 默认情况下,任何服务都可以以该服务的名称到达任何其他服务。 (实际是通过设置/etc/hosts的域名解析,从而实现容器间的通信。故可以像在应用中使用localhost一样使用服务的别名链接其他容器的服务,前提是多个服务容器在一个网络中可路由联通)
links也可以起到和depends_on相似的功能,即定义服务之间的依赖关系,从而确定服务启动的顺序。
2.3.13 volumes
指定宿主机目录和容器目录映射,如果一个主机目录只是由单个服务使用,可以直接在服务定义里面配置,如果一个路径要跨多个服务复用,则必须在顶层的volumes中配置。
volumes支持短语法和长语法。
短语法:
使用一个带有冒号分隔值的字符串来指定卷装入(VOLUME:CONTAINER_PATH),或访问模式(VOLUME:CONTAINER_PATH:ACCESS_MODE).
- VOLUME:主机目录
- CONTAINER_PATH: 容器目录
- ACCESS_MODE:访问模式,可用值包括rw(默认值,读写)、ro(只读)、z、Z,后两个为SELinux特有。
可以在主机上挂载相对路径,该路径将相对于当前正在使用的Compose配置文件的目录进行扩展。相对路径应始终以 . 或者 … 开始。
volumes:
# 只需指定一个路径,让引擎创建一个卷
- /var/lib/mysql
# 指定绝对路径映射
- /opt/data:/var/lib/mysql
# 相对于当前compose文件的相对路径
- ./cache:/tmp/cache
# 用户家目录相对路径
- ~/configs:/etc/configs/:ro
# 命名卷
- datavolume:/var/lib/mysql
长语法:
允许配置短格式中无法表示的其他字段,详细请查阅官方文档。
services:
backend:
image: awesome/backend
volumes:
- type: volume # 装载类型,可用值volume,bind,tmpfs或npipe
source: db-data # 宿主机路径或者顶层volumes中定义的卷,不适应于type时tmpfs时
target: /data # 容器内部路径
read_only: false # 是否只读
volume: # 配置其他卷选项
nocopy: true # 配置卷创建的是否从容器内部复制数据
- type: bind # 绑定模式时,还可以通过bind指令配置其他绑定选项
source: /var/run/postgres/postgres.sock
target: /var/run/postgres/postgres.sock
volumes:
db-data:
2.3.14 volumes_from
定义与其他容器或服务中的卷进行共享映射
volumes_from:
- service_name
- service_name:ro
- container:container_name
- container:container_name:rw
2.3.15 configs
为每个服务授予对配置(configs)的访问权限。支持short和long两种格式的语法。更多configs信息,参考configs。
注意:该配置(config)必须已存在或者在堆栈文件顶层configs配置项中定义,否则堆栈部署将失败。
短语法仅指定config名称来授予容器访问config的权限并将其挂载到容器的/<config_name>上。source名称和目标挂载点都设置为config名称。
例如以下示例,授予了redis服务对configs的my_config和my_other_config的访问权限,其中my_config的值设置到文件./my_config.txt的内容中,my_other_config定义为外部资源,这意味着它已经在Docker中通过运行docker config create命令或其他堆栈部署进行定义,如果外部config不存在,堆栈部署将会失败并显示config not found错误
services:
redis:
image: redis:latest
deploy:
replicas: 1
configs:
- my_config
- my_other_config
configs:
my_config:
file: ./my_config.txt
my_other_config:
external: true
长语法提供了在服务的任务容器内如何创建config的更多粒度:
- source:Docker中存在的config名称。
- target:指定要挂载到服务的任务容器的文件的路径加名称。如果未指定,默认为/。
- uid和gid:指定服务的任务容器所拥有的该文件的UID或GID。如果在LInux中未指定,两者都默认为0。不支持Windows。
- mode:以八进制表示法指定要挂载到服务的任务容器的文件权限。例如,0444代表可读。默认值就为0444。config内容已挂载到临时文件系统中,所以不可写,如果设置了可写位将被忽略。可以设置可执行位。如果不熟悉UNIX文件权限模式,可以使用权限计算器 。
例如以下示例,指定config名称为my_config,授予redis服务对my_config的访问权限,指定要挂载到redis服务的任务容器的路径加文件名称为/redis_config,指定UID和GID均为103,指定要挂载到服务的任务容器的文件权限为0440(group-readable),但该redis服务没有访问my_other_config的权限:
services:
redis:
image: redis:latest
deploy:
replicas: 1
configs:
- source: my_config
target: /redis_config
uid: '103'
gid: '103'
mode: 0440
configs:
my_config:
file: ./my_config.txt
my_other_config:
external: true
可以授予服务访问多个config的权限,并且可以混合long和short语法。定义config并不意味着授予服务对其的访问权限。
2.3.16 Healthcheck
声明一个用于确定此服务的容器是否“正常”的检查。这会覆盖Dockerfile文件中设置的HEALTHCHECK指令。
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
interval: 1m30s # 设置检测间隔
timeout: 10s # 设置检测超时时间
retries: 3 #设置重试次数
start_period: 40s # 启动后,多少秒开始启动检测程序
test也可以用shell格式:
test: curl -f https://localhost || exit 1
也可以用以下指令禁用镜像自带的健康状态检查:
healthcheck:
disable: true
2.3.17 logging
定义服务的日志记录配置
logging:
driver: syslog
options:
syslog-address: "tcp://192.168.0.42:123"
driver指定服务容器的日志驱动程序,默认值和可用值特定于平台,options的配置也会因驱动不同而不同。如上面的例子,配置驱动为syslog,可以使用 syslog-address 指定日志接收地址。
driver有以下三个可用值:
- driver: “json-file”
- driver: “syslog”
- driver: “none”
在 json-file 驱动程序下,可以使用以下参数,限制日志得数量和大小。
logging:
driver: json-file
options:
max-size: "200k" # 单个文件大小为200k
max-file: "10" # 最多10个文件
当达到文件限制上限,会自动删除旧得文件。
关于docker日志记录方式可参考: https://mp.weixin.qq.com/s/fq8DNj6Ipt6V5y0xBxXjdA
2.3.18 restart
配置容器退出时的应对策略,可用值如下:
- no:是默认的重启策略,在任何情况下都不会重启容器。
- always:容器总是重新启动。
- on-failure:在容器非正常退出时(退出状态非0),才会重启容器。
- unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped
2.3.19 scale
配置一个服务启动容器的个数,不过这个指令已经被deploy指令中的replicas替代了,虽然还可以使用,但是会产生警告。
services:
redis:
image: redis:alpine
scale: 2
可用以下方式:
services:
mysql:
image: redis:alpine
deploy:
replicas: 2
这样子redis服务会启动两个容器,容器名称会以"项目名(没有配置的话默认文件名) -服务名(这里就是redis)-序号"命名,由于容器名称不能重复,所以在一个服务启动多个容器的情况下不能配置container_name。
2.3.20 deploy
指定部署和运行服务的相关配置。
例如:
version: "3.9"
services:
redis:
image: redis:alpine
deploy:
replicas: 6
placement:
max_replicas_per_node: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
deploy配置项中包含endpoint_mode、labels、mode、placement、replicas、resources、restart_policy、update_config等子配置项。
(1) endpoint_mode
在3.2版的配置文件格式中加入
为外部客户端连接到swarm指定服务发现方式:
- endpoint_mode: vip:Docker为服务分配了一个前端的虚拟IP,客户端通过该虚拟IP访问网络上的服务。Docker在客户端和服务的可用工作节点之间进行路由请求,而无须关系有多少节点正在参与该服务或这些节点的IP地址或者端口。这是默认设置。
- endpoint_mode: dnsrr:DNS轮询(DNSRR),Docker设置服务的DNS条目,以便对服务名称的DNS查询返回IP地址列表,并且客户端通过轮询的方式直接连接到其中之一。
例如:
services:
redis:
image: redis:alpine
deploy:
replicas: 6
placement:
max_replicas_per_node: 1
update_config:
parallelism: 2
delay: 10s
restart_policy:
condition: on-failure
(2) labels
指定服务的标签。这些标签仅在服务上设置,而不在服务的任何容器上设置。
例如:
services:
web:
image: web
deploy:
labels:
com.example.description: "This label will appear on the web service"
(3) mode
指定服务的容器副本模式。可以为:
- global:每个swarm节点只有一个该服务容器。
- replicated:整个集群中存在指定份数的服务容器副本,为默认值。
例如,指定容器副本模式为global:
services:
worker:
image: dockersamples/examplevotingapp_worker
deploy:
mode: global
(4) placement
指定constraints和preferences。constraints可以指定只有符合要求的节点上才能运行该服务容器,preferences可以指定容器分配策略。例如,指定集群中只有满足node.rolemanager和engine.labels.operatingsystemubuntu 18.04条件的节点上能运行db服务容器,并且在满足node.labels.zone的节点上均匀分配:
services:
db:
image: postgres
deploy:
placement:
constraints:
- "node.role==manager"
- "engine.labels.operatingsystem==ubuntu 18.04"
preferences:
- spread: node.labels.zone
(5) max_replicas_per_node
在3.8版的配置文件格式中加入
如果服务的容器副本模式为replicated(默认),可以指定每个节点上运行的最大容器副本数量。当指定的容器副本数量大于最大容器副本数量时,将引发no suitable node (max replicas per node limit exceed)错误。
例如:
services:
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 6
placement:
max_replicas_per_node: 1
(6) replicas
如果服务的容器副本模式为replicated(默认),指定运行的容器副本数量。例如:
services:
worker:
image: dockersamples/examplevotingapp_worker
networks:
- frontend
- backend
deploy:
mode: replicated
replicas: 6
(7) resources
配置资源限制。例如,指定redis服务使用的cpu份额为25%到50%,内存为20M到50M
services:
redis:
image: redis:alpine
deploy:
resources:
limits:
cpus: '0.50'
memory: 50M
reservations:
cpus: '0.25'
memory: 20M
在V3版Compose配置文件中的改变:resources取代了V3版之前的Compose配置文件中旧的资源限制的配置项,包括cpu_shares、cpu_quota、cpuset、mem_limit、memswap_limit、mem_swappiness。
在非swarm mode容器上设置资源限制:此处的resources配置项只有用于deploy配置项之下和swarm mode。如果要在非swarm mode部署中设置资源限制,需使用V2版Compose配置文件中CPU、memory和其他资源的配置项。
(8) restart_policy
指定容器的重启策略。代替restart。有以下配置选项:
- condition:重启策略。值可以为none、on-failure或any,默认为any。
- delay:尝试重启的等待时间。指定为持续时间(durations)。默认值为0。
- max_attempts:重启最多尝试的次数,超过该次数将放弃。默认为永不放弃。如果在window配置的时间之内未成功重启,则此次尝试不计入max_attempts的值。
- window:在决定重启是否成功之前的等待时间。指定为持续时间(durations)。默认值为立即决定。
例如,指定重启策略为失败时重启,等待5s,重启最多尝试3次,决定重启是否成功前的等待时间为120s:
services:
redis:
image: redis:alpine
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
(9) rollback_config
在3.7版的配置文件格式中加入
配置在更新失败的情况下如何回滚服务。有以下配置选项:
- parallelism:一次回滚的容器数量。如果设置为0,则所有容器同时回滚。
- delay:每个容器组之间的回滚所等待的时间。默认值为0s。
- failure_action:回滚失败后的行为。有continue和pause两种,默认值为pause。
- monitor:每次任务更新后监视失败的时间(ns|us|ms|s|m|h)。默认值为0s。
- max_failure_ratio:在回滚期间能够容忍的最大失败率。默认值为0。
- order:设置回滚顺序。stop-first为在开启新任务之前停止旧任务,start-first为首先启动新任务,和正在运行任务短暂重叠,默认值为stop-first。
(10)update_config
配置如何更新服务。该配置对滚动更新很有用。有以下配置选项: - parallelism:一次更新的容器数量。
- delay:更新一组容器之间的等待时间。
- failure_action:更新失败后的行为。有continue、rollback和pause三种,默认值为pause。
- monitor:每次任务更新后监视失败的时间(ns|us|ms|s|m|h)。默认值为0s。
- max_failure_ratio:在更新期间能够容忍的最大失败率。
- order:设置更新顺序。stop-first为在开启新任务之前停止旧任务,start-first为首先启动新任务,和正在运行任务短暂重叠,默认值为stop-first。注意该配置项在3.4版的配置文件格式中加入,仅支持3.4或更高版本。
例如,指定每次更新2个容器,更新等待时间10s,更新顺序为先停止旧任务再开启新任务:
services:
vote:
image: dockersamples/examplevotingapp_vote:before
depends_on:
- redis
deploy:
replicas: 2
update_config:
parallelism: 2
delay: 10s
order: stop-first
2.4 networks
网络是允许服务彼此通信的层,可以通过在顶层下指定网络名称来创建网络,服务可以通过在服务下指定网络名称来连接到网络,连接到相同网络的服务能够进行相互通讯。如果没有显式配置网络,则compose在编排的时候会创建默认网络。
services:
redis:
image: redis:alpine
如上面compose.yaml文件使用docker compose config命令可以看到自动帮我们添加上了网络配置。
networks顶层节点可以配置driver、name、label、ipam等属性,具体请查阅官方文档。
2.5 volumes
卷是平台实现的持久数据存储。Compose规范为挂载卷的服务提供了一个中立的抽象,并提供了在基础设施上分配卷的配置参数。可以通过在顶层的volumes配置公共卷,然后在不同的服务中复用。
services:
backend:
image: awesome/database
volumes:
- db-data:/etc/data
backup:
image: backup-service
volumes:
- db-data:/var/lib/backup/data
volumes:
db-data:
如上面的例子,顶层以下的入口volumes键可以为空,在这种情况下,它使用平台的默认配置来创建卷,也可以通过参数对其进行配置,可以用参数包括driver、driver_opts、name、label、external等。其中的需要注意的是,external参数配置为true时,compose会查找外部存在的卷,如果找不到就会编排失败,不会自动创建卷。
顶层volumes键为空的情况下默认创建的卷,我们不知道数据存在本地什么位置,可以通过以下的方式查找对应的卷
通过我们定义的卷名查找卷标:
docker volume ls | grep db-data
通过卷标查找卷的元信息:
docker volume ls | grep db-data
2.6 configs
顶层configs配置项定义或引用了授予此堆栈中的服务的configs,config来源于file或external。相关配置项如下。
- file:通过指定路径中的文件内容创建config。
- external:如果设置为true,则指定该config已经创建。Docker不会尝试创建它,如果它不存在,会发生config not found错误。
- name:指定Docker中config的名称。在3.5版的配置文件格式中加入。
- driver和driver_opts:自定义secret驱动的名称,和以键值对的形式指定用来传递给特定驱动的选项。这两个配置项均在3.8版的配置文件格式中加入,仅在使用docker stack时受支持。
- template_driver:指定要使用的模板驱动的名称,它控制是否以及如何将secret有效负载作为模板进行评估。如果未设置驱动,则不使用任何模板。当前仅支持使用Go语言的golang驱动。该配置项在3.8版的配置文件格式中加入,仅在使用docker stack时受支持。
2.7 secrests
顶层secrets配置项定义或引用了授予此堆栈中的服务的secrets,secret来源于file或external。相关配置项如下。
- file:通过指定路径中的文件内容创建secret。
- external:如果设置为true,则指定该secret已经创建。Docker不会尝试创建它,如果它不存在,会发生secretg not found错误。
- name:指定Docker中secret的名称。在3.5版的配置文件格式中加入。
- template_driver:指定要使用的模板驱动的名称,它控制是否以及如何将secret有效负载作为模板进行评估。如果未设置驱动,则不使用任何模板。当前仅支持使用Go语言的golang驱动。该配置项在3.8版的配置文件格式中加入,仅在使用docker stack时受支持。
3. docker compose常用命令
docker compose命令基本格式如下:
docker compose [OPTIONS] [COMMAND] [ARGS] [SERVICES]
在没有特别说明的情况下,命令对象是项目,项目中所有的服务都会受到命令影响,可以通过指定服务名称只针对某些服务进行操作。
可以通过 docker compose COMMAND --help 查看具体命令的帮助文档。
常用的[OPTIONS]如下,
-f:指定编码文件,可以多次使用编排多个项目
-p: 指定项目名称,这里指定的名称会覆盖文件中的name或者默认的名称
-env-file: 指定环境变量文件
如:
docker compose -f my-compose.yaml -f compose.yaml up -d
常用的命令如下:
3.1 docker compose [OPTIONS] config [ARGS] [SERVICES]
config命令用于验证 Compose 文件格式是否正确,若正确则显示配置,若格式错误显示错误原因,并不会执行真正的操作。
3.2 docker compose [OPTIONS] up [ARGS] [SERVICES]
up 命令十分强大,它将尝试自动完成包括构建镜像,创建服务,启动服务,并关联服务相关容器的一系列操作。依赖的服务都也会被自动启动,除非依赖的服务已经处于运行状态。
大部分时候都可以直接通过该命令来启动一个项目。默认情况,docker-compose up 启动的容器都在前台,控制台将会
同时打印所有容器的输出信息,可以很方便进行调试。当通过 Ctrl-C 停止命令时,所有容器将会停止。
如果使用 docker-compose up -d,将会在后台启动并运行所有的容器。一般推荐生产环境下使用该选项。
如果服务容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),
以保证新启动的服务匹配 compose.yaml 文件的最新内容。
up命令的参数如下:
-d 在后台运行服务容器。
–no-color 不使用颜色来区分不同的服务的控制台输出。
–no-deps 不启动服务所链接的容器。
–force-recreate 强制重新创建容器,不能与 --no-recreate 同时使用。
–no-recreate 如果容器已经存在了,则不重新创建,不能与 --force-recreate 同时使用。
–no-build 不自动构建缺失的服务镜像。
-t, --timeout TIMEOUT 停止容器时候的超时(默认为 10 秒)。
–scale 在启动的时候设置一个服务启动多少个容器,会覆盖compose.yaml文件中的设置
在 docker-compose up 命令最后加上服务名称时,可以只对某一个或几个服务进行操作。
3.3 docker compose [OPTIONS] down [ARGS] [SERVICES]
down命令默认会停止并移除 up 命令所启动的容器和创建的网络,但不会移除数据卷。
一样可以在命令后面加上服务名称,只针对特定服务进行操作
down命令的参数如下:
通过参数-v和–rmi,也可以移除compose.yaml文件中定义的卷和服务容器使用到的镜像。
3.4 docker compose [OPTIONS] ps [ARGS] [SERVICES]
列出项目中目前的所有容器。
ps命令的参数如下:
-a 列出所有的服务,包括已经停止的
-q 只列出服务id
-status 通过状态过滤服务,只列出特定状态的服务
3.5 docker compose [OPTIONS] exec [ARGS] [SERVICES] [COMMOND][COMMONDARGS]
通过某个正在运行的容器执行命令
如进入容器内部
docker compose exec compose-nginx-1 /bin/bash
如直接执行命令
docker compose exec compose-nginx-1 ls
exec命令的参数如下:
-e 设置容器环境变量
–index 一个服务有多个实例的情况,指定在第几个实例执行
-u 指定用哪个用户执行命令
-w 指定命令执行的工作目录
3.6 docker compose [OPTIONS] start [SERVICES]
启动服务容器
3.7 docker compose [OPTIONS] stop [SERVICES]
停止服务容器
3.8 docker compose[OPTIONS] restart [ARGS][SERVICES]
重新启动所有已停止并正在运行的服务容器。
选项:
-t, --timeout TIMEOUT 指定重启前停止容器的超时(默认为 10 秒)。
3.9 docker compose [OPTIONS] pause [SERVICES]
暂停服务容器
3.10 docker compose [OPTIONS] unpause [SERVICES]
恢复处于暂停状态中的服务容器
3.11 docker compose [OPTIONS] kill [ARGS] [SERVICES]
强制停止服务的容器,可通过-s参数给容器发送信号,默认信号为SIGKILL
3.12 docker compose [OPTIONS] rm [ARGS] [SERVICES]
删除所有(停止状态的)服务容器。推荐先执行 docker compose stop 命令来停止容器。
-f, --force 强制直接删除,包括非停止状态的容器。一般尽量不要使用该选项。
-s 在移除之前先停止容器
-v 删除容器所挂载的数据卷。
3.13 docker compose [OPTIONS] cp [ARGS]
在服务容器和宿主机之间复制文
docker compose [OPTIONS] cp [ARGS] SERVICE:SRC_PATH DEST_PATH # 从容器内部复制到本地
docker compose [OPTIONS] cp [ARGS] SRC_PATH SERVICE:DEST_PATH # 从本地复制到容器内部
可用参数如下:
–all 复制到服务的所有容器
–index 一个服务多个容器的情况看下指定第几个容器
3.14 docker compose [OPTIONS] events [ARGS] [SERVICES]
接收服务容器的实时事件。
3.15 docker compose [OPTIONS] logs [ARGS] [SERVICES]
查看服务容器的输出。默认情况下,docker-compose 将对不同的服务输出使用不同的颜色来区分。
可用参数如下:
–no-color 关闭颜色
–since 接收时间戳字符串,只展示时间戳对应时间之后的日志
–tail 设置只展示最后多少行日志
–t 展示日志时间戳
3.16 docker compose [OPTIONS] top [SERVICES]
查看项目中服务容器内运行的进程
3.17 docker compose [OPTIONS] top [ARGS] SERVICE PRIVATE_PORT
查看服务容器内部端口映射到宿主机的哪个端口
–index 如果服务启动了多个容器的话,指定查看哪个容器
–protocol 指定协议,tcp或者udp
Docker compose相关的知识点到这里就已经介绍完毕了,如果看完上面的内容,大家对docker compose的作用和常用的操作应该也相对了解了。
利用docker compose,我们可以快速地启动一个项目的若干容器,让它们协调工作,并且能够对这些容器对进行敏捷的生命周期的管理。但是docker compose有一个缺点,那就是它只能在单个服务器或主机上创建多个容器,无法实现跨服务器的容器编排部署。
目前我们所讲到的所有容器的使用都是在单服务器的情况下进行的,但是在微服务架构下,随着业务的扩展,服务越来越多,总不能一直将所有服务及其依赖全部部署在一台机器上,这样服务器撑不住,也失去了分布式架构的意义。
当你看到这里,开始思考如何利用多台主机进行快速部署,就逐渐进入了容器集群的世界了。对容器集群进行管理也有各种各样的工具,这一篇从单机到集群进行过渡,下一篇开始就进入容器集群世界了。
微服务系列文章:
上一篇:容器技术—.net core on docker
下一篇:容器技术—docker swarm(一)
更多推荐
所有评论(0)