码头服务创建
描述 | 创建新服务 |
---|---|
用法 | docker service create [OPTIONS] IMAGE [COMMAND] [ARG...] |
Swarm 此命令与 Swarm 协调器配合使用。
描述
按照指定参数的描述创建服务。
笔记
这是集群管理命令,必须在 swarm manager 节点上执行。要了解管理器和工作器,请参阅 文档中的Swarm 模式部分。
选项
选项 | 默认 | 描述 |
---|---|---|
--cap-add | API 1.41+ 添加 Linux 功能 | |
--cap-drop | API 1.41+ 放弃 Linux 功能 | |
--config | API 1.30+ 指定向服务公开的配置 | |
--constraint | 布局限制 | |
--container-label | 容器标签 | |
--credential-spec | 托管服务帐户的API 1.29+ 凭据规范(仅限 Windows) | |
-d, --detach | API 1.29+ 立即退出而不是等待服务收敛 | |
--dns | API 1.25+ 设置自定义 DNS 服务器 | |
--dns-option | API 1.25+ 设置 DNS 选项 | |
--dns-search | API 1.25+ 设置自定义 DNS 搜索域 | |
--endpoint-mode | vip | 端点模式(vip 或 dnsrr) |
--entrypoint | 覆盖图像的默认ENTRYPOINT | |
-e, --env | 设置环境变量 | |
--env-file | 读入环境变量文件 | |
--generic-resource | 用户定义的资源 | |
--group | API 1.25+ 为容器设置一个或多个补充用户组 | |
--health-cmd | API 1.25+ 运行命令来检查运行状况 | |
--health-interval | API 1.25+ 运行检查之间的时间 (ms|s|m|h) | |
--health-retries | API 1.25+ 需要连续失败才能报告不健康 | |
--health-start-interval | API 1.44+ 在开始期间运行检查之间的时间 (ms|s|m|h) | |
--health-start-period | API 1.29+
在对不稳定进行重试计数之前容器初始化的开始时间 (ms|s|m|h) | |
--health-timeout | API 1.25+ 允许运行一项检查的最长时间 (ms|s|m|h) | |
--host | API 1.25+ 设置一个或多个自定义主机到 IP 映射 (host:ip) | |
--hostname | API 1.25+ 容器主机名 | |
--init | API 1.37+
在每个服务容器内使用 init 来转发信号并获取进程 | |
--isolation | API 1.35+ 服务容器隔离模式 | |
-l, --label | 服务标签 | |
--limit-cpu | 限制CPU数量 | |
--limit-memory | 限制内存 | |
--limit-pids | API 1.41+ 限制最大进程数(默认 0 = 无限制) | |
--log-driver | 记录服务驱动程序 | |
--log-opt | 记录驱动程序选项 | |
--max-concurrent | API 1.41+
同时运行的作业任务数(默认等于--replicas) | |
--mode | replicated | 服务模式 ( replicated , global , replicated-job , global-job ) |
--mount | 将文件系统挂载附加到服务 | |
--name | 服务名称 | |
--network | 网络附件 | |
--no-healthcheck | API 1.25+ 禁用任何容器指定的 HEALTHCHECK | |
--no-resolve-image | API 1.30+
不查询注册表来解析图像摘要和支持的平台 | |
--placement-pref | API 1.28+ 添加放置首选项 | |
-p, --publish | 将端口发布为节点端口 | |
-q, --quiet | 抑制进度输出 | |
--read-only | API 1.28+ 将容器的根文件系统挂载为只读 | |
--replicas | 任务数量 | |
--replicas-max-per-node | API 1.40+ 每个节点的最大任务数(默认 0 = 无限制) | |
--reserve-cpu | 预留CPU | |
--reserve-memory | 预留内存 | |
--restart-condition | 满足条件时重新启动 ( none , on-failure , any )(默认any ) | |
--restart-delay | 重新启动尝试之间的延迟 (ns|us|ms|s|m|h)(默认 5 秒) | |
--restart-max-attempts | 放弃前最大重启次数 | |
--restart-window | 用于评估重启策略的窗口 (ns|us|ms|s|m|h) | |
--rollback-delay | API 1.28+ 任务回滚之间的延迟 (ns|us|ms|s|m|h)(默认 0s) | |
--rollback-failure-action | API 1.28+
回滚失败时的操作 ( pause , continue )(默认pause ) | |
--rollback-max-failure-ratio | API 1.28+ 回滚期间容忍的失败率(默认 0) | |
--rollback-monitor | API 1.28+
每次任务回滚后监视失败的持续时间 (ns|us|ms|s|m|h)(默认 5 秒) | |
--rollback-order | API 1.29+
回滚顺序 ( start-first , stop-first )(默认stop-first ) | |
--rollback-parallelism | 1 | API 1.28+
同时回滚的最大任务数(0表示一次全部回滚) |
--secret | API 1.25+ 指定向服务公开的秘密 | |
--stop-grace-period | 强制杀死容器之前等待的时间 (ns|us|ms|s|m|h)(默认 10 秒) | |
--stop-signal | API 1.28+ 停止容器的信号 | |
--sysctl | API 1.40+ Sysctl 选项 | |
-t, --tty | API 1.25+ 分配伪 TTY | |
--ulimit | API 1.41+ Ulimit 选项 | |
--update-delay | 更新之间的延迟 (ns|us|ms|s|m|h)(默认 0s) | |
--update-failure-action | 更新失败时的操作 ( pause , continue , rollback )(默认pause ) | |
--update-max-failure-ratio | API 1.25+ 更新期间容忍的失败率(默认 0) | |
--update-monitor | API 1.25+
每个任务更新后监视失败的持续时间 (ns|us|ms|s|m|h)(默认 5 秒) | |
--update-order | API 1.29+
更新顺序 ( start-first , stop-first )(默认stop-first ) | |
--update-parallelism | 1 | 同时更新的最大任务数(0 表示一次更新所有任务) |
-u, --user | 用户名或 UID(格式:<name|uid>[:<group|gid>]) | |
--with-registry-auth | 将注册表身份验证详细信息发送给 Swarm 代理 | |
-w, --workdir | 容器内的工作目录 |
例子
创建服务
$ docker service create --name redis redis:3.0.6
dmu1ept4cxcfe8k8lhtux3ro3
$ docker service create --mode global --name redis2 redis:3.0.6
a8q9dasaafudfs8q8w32udass
$ docker service ls
ID NAME MODE REPLICAS IMAGE
dmu1ept4cxcf redis replicated 1/1 redis:3.0.6
a8q9dasaafud redis2 global 1/1 redis:3.0.6
使用私有注册表上的映像创建服务 (--with-registry-auth)
如果您的映像在需要登录的私有注册表上可用,请在登录后使用带有
--with-registry-auth
, 的标志docker service create
。如果您的映像存储在registry.example.com
私有注册表上,请使用如下命令:
$ docker login registry.example.com
$ docker service create \
--with-registry-auth \
--name my_service \
registry.example.com/acme/my_image:latest
这将使用加密的 WAL 日志将登录令牌从本地客户端传递到部署服务的 swarm 节点。有了这些信息,节点就可以登录注册表并提取映像。
创建具有 5 个副本任务的服务 (--replicas)
使用该--replicas
标志可以设置复制服务的副本任务数。以下命令创建redis
具有5
副本任务的服务:
$ docker service create --name redis --replicas=5 redis:3.0.6
4cdgfyky7ozwh3htjfw0d12qv
上述命令设置服务所需的任务数量。尽管命令立即返回,但服务的实际扩展可能需要一些时间。该REPLICAS
列显示服务的实际副本任务数和所需副本任务数。
在以下示例中,所需状态是5
副本,但当前任务数RUNNING
是3
:
$ docker service ls
ID NAME MODE REPLICAS IMAGE
4cdgfyky7ozw redis replicated 3/5 redis:3.0.7
一旦创建了所有任务 和RUNNING
,实际任务数量就等于所需数量:
$ docker service ls
ID NAME MODE REPLICAS IMAGE
4cdgfyky7ozw redis replicated 5/5 redis:3.0.7
创建带有机密的服务 (--secret)
使用该--secret
标志为容器提供对
机密的访问权限。
创建指定秘密的服务:
$ docker service create --name redis --secret secret.json redis:3.0.6
4cdgfyky7ozwh3htjfw0d12qv
创建指定密钥、目标、用户/组 ID 和模式的服务:
$ docker service create --name redis \
--secret source=ssh-key,target=ssh \
--secret source=app-key,target=app,uid=1000,gid=1001,mode=0400 \
redis:3.0.6
4cdgfyky7ozwh3htjfw0d12qv
要授予服务访问多个机密的权限,请使用多个--secret
标志。
/run/secrets
如果未指定目标,则机密位于容器中。如果未指定目标,则秘密的名称将用作容器中的内存文件。如果指定了目标,则将其用作文件名。在上面的示例中,为每个指定的秘密目标创建了两个文件:/run/secrets/ssh
和
。/run/secrets/app
使用配置创建服务 (--config)
使用该--config
标志授予容器对
config 的访问权限。
使用配置创建服务。配置将被挂载到redis-config
,由在容器内运行命令的用户(通常)拥有root
,并且具有文件模式0444
或世界可读。您可以将uid
和指定gid
为数字 ID 或名称。使用名称时,提供的组/用户名必须预先存在于容器中。被mode
指定为 4 个数字序列,例如0755
。
$ docker service create --name=redis --config redis-conf redis:3.0.6
使用配置创建服务并指定目标位置和文件模式:
$ docker service create --name redis \
--config source=redis-conf,target=/etc/redis/redis.conf,mode=0400 redis:3.0.6
要授予服务访问多个配置的权限,请使用多个--config
标志。
/
如果未指定目标,配置位于容器中。如果未指定目标,则配置的名称将用作容器中文件的名称。如果指定了目标,则将其用作文件名。
创建具有滚动更新策略的服务
$ docker service create \
--replicas 10 \
--name redis \
--update-delay 10s \
--update-parallelism 2 \
redis:3.0.6
当您运行
服务更新时,计划程序一次最多更新 2 个任务(10s
更新之间)。有关更多信息,请参阅
滚动更新教程。
设置环境变量(-e、--env)
这为服务中的所有任务设置一个环境变量。例如:
$ docker service create \
--name redis_2 \
--replicas 5 \
--env MYVAR=foo \
redis:3.0.6
要指定多个环境变量,请指定多个--env
标志,每个标志都有一个单独的键值对。
$ docker service create \
--name redis_2 \
--replicas 5 \
--env MYVAR=foo \
--env MYVAR2=bar \
redis:3.0.6
创建具有特定主机名的服务 (--hostname)
此选项将 docker 服务容器主机名设置为特定字符串。例如:
$ docker service create --name redis --hostname myredis redis:3.0.6
设置服务的元数据(-l、--label)
标签是key=value
将元数据应用于服务的一对。使用两个标签来标记服务:
$ docker service create \
--name redis_2 \
--label com.example.foo="bar" \
--label bar=baz \
redis:3.0.6
有关标签的更多信息,请参阅 应用自定义元数据。
添加绑定挂载、卷或内存文件系统 (--mount)
Docker 支持三种不同类型的挂载,允许容器在主机操作系统或内存文件系统上读取或写入文件或目录。这些类型是数据卷(通常简称为卷)、绑定挂载、tmpfs 和命名管道。
绑定挂载使主机上的文件或目录可供其挂载的容器使用。绑定安装可以是只读的或读写的。例如,容器可能通过主机的绑定挂载来共享其主机的 DNS 信息/etc/resolv.conf
,或者容器可能将日志写入其主机的/var/log/myContainerLogs
目录。如果您使用绑定安装,并且您的主机和容器具有不同的权限概念、访问控制或其他此类细节,您将遇到可移植性问题。
命名卷是一种机制,用于将容器所需的持久数据与用于创建容器的映像和主机解耦。命名卷由 Docker 创建和管理,即使当前没有容器使用命名卷,它也会持续存在。命名卷中的数据可以在容器和主机之间以及多个容器之间共享。 Docker 使用卷驱动程序来创建、管理和挂载卷。您可以使用 Docker 命令备份或恢复卷。
tmpfs将 tmpfs 安装在容器内以存储易失性数据。
npipe将命名管道从主机安装到容器中。
考虑一下您的图像启动轻量级 Web 服务器的情况。您可以使用该图像作为基础图像,复制网站的 HTML 文件,然后将其打包到另一个图像中。每次您的网站发生更改时,您都需要更新新映像并重新部署为您的网站提供服务的所有容器。更好的解决方案是将网站存储在命名卷中,该卷在启动时附加到每个 Web 服务器容器。要更新网站,您只需更新指定的卷即可。
有关命名卷的更多信息,请参阅 数据卷。
下表描述了适用于服务中的绑定安装和命名卷的选项:
选项 | 必需的 | 描述 |
---|---|---|
类型 | 挂载的类型可以是volume、bind、tmpfs或npipe。如果未指定类型,则默认为体积。
| |
src或来源 | 对于type=bind和type=npipe |
|
dst或目的地或目标 | 是的 | 容器内的挂载路径,例如/some/path/in/container/。如果容器的文件系统中不存在该路径,引擎会在挂载卷或绑定挂载之前在指定位置创建一个目录。 |
只读或只读 | 引擎以读写方式挂载绑定和卷,除非在挂载绑定或卷时给出只读选项。请注意,为绑定挂载设置只读可能不会使其子挂载只读,具体取决于内核版本。另请参见绑定递归。
|
绑定安装选项
以下选项只能用于绑定安装 ( type=bind
):
选项 | 描述 |
---|---|
绑定传播 | 请参阅绑定传播部分。 |
一致性 | 安装的一致性要求;之一
|
绑定递归 | 默认情况下,子挂载也是递归绑定挂载的。但是,当使用只读选项配置绑定挂载时,此行为可能会令人困惑,因为根据内核版本,子挂载可能不会挂载为只读。设置bind-recursive以控制递归绑定安装的行为。 值是以下之一:
|
绑定非递归 | 自 Docker Engine v25.0 起,bind-nonrecursive已被弃用。请改用绑定递归。 值是可选的:
|
绑定传播
绑定传播是指在给定绑定安装或命名卷中创建的安装是否可以传播到该安装的副本。考虑一个安装点/mnt
,它也安装在/tmp
.传播设置控制 上的安装是否/tmp/a
也可在 上使用/mnt/a
。每个传播设置都有一个递归对位。在递归的情况下,请考虑将/tmp/a
也安装为/foo
。传播设置控制是否存在/mnt/a
和/或/tmp/a
将存在。
该bind-propagation
选项默认适用rprivate
于绑定安装和卷安装,并且只能针对绑定安装进行配置。换句话说,命名卷不支持绑定传播。
shared
:原始挂载的子挂载会暴露给副本挂载,并且副本挂载的子挂载也会传播到原始挂载。slave
:与共享安装类似,但仅限一个方向。如果原始安装公开了子安装,则副本安装可以看到它。但是,如果副本安装公开了子安装,则原始安装将看不到它。private
:坐骑是私人的。其中的子安装不会暴露给副本安装,并且副本安装的子安装不会暴露给原始安装。rshared
:与共享相同,但传播也会扩展到嵌套在任何原始或副本安装点内的安装点。rslave
:与 相同slave
,但传播也会扩展到嵌套在任何原始或副本安装点内的安装点。rprivate
:默认。与 相同private
,这意味着原始安装点或副本安装点内的任何位置都没有安装点以任一方向传播。
有关绑定传播的更多信息,请参阅 共享子树的 Linux 内核文档。
命名卷的选项
以下选项只能用于命名卷 ( type=volume
):
选项 | 描述 |
---|---|
音量驱动程序 | 用于卷的卷驱动程序插件的名称。默认为 "local",如果卷不存在,则使用本地卷驱动程序创建卷。 |
体积标识 | 创建卷时应用到卷的一个或多个自定义元数据(“标签”)。例如, volume-label=mylabel=hello-world,my-other-label=hello-mars。有关标签的更多信息,请参阅 应用自定义元数据。 |
卷无复制 | 默认情况下,如果将空卷附加到容器,并且文件或目录已存在于容器的安装路径 ( dst ) 中,引擎会将这些文件和目录复制到该卷中,从而允许主机访问它们。设置volume-nocopy以禁止将文件从容器的文件系统复制到卷并挂载空卷。 值是可选的:
|
音量选择 | 特定于给定卷驱动程序的选项,这些选项将在创建卷时传递给驱动程序。选项以逗号分隔的键/值对列表的形式提供,例如, volume-opt=some-option=some-value,volume-opt=some-other-option=some-other-value。有关给定驱动程序的可用选项,请参阅该驱动程序的文档。 |
tmpfs 的选项
以下选项只能用于 tmpfs 挂载 ( type=tmpfs
);
选项 | 描述 |
---|---|
tmpfs 大小 | tmpfs 安装的大小(以字节为单位)。 Linux 中默认无限制。 |
tmpfs 模式 | tmpfs 的文件模式(八进制)。 (例如“700”或“0700” 。)在 Linux 中默认为“1777” 。 |
“--mount”和“--volume”之间的区别
该--mount
标志支持-v
或--volume
标志支持的大多数选项docker run
,但有一些重要的例外:
该
--mount
标志允许您指定卷驱动程序和每个卷的卷驱动程序选项,而无需提前创建卷。相反,docker run
允许您使用该标志指定由所有卷共享的单个卷驱动程序--volume-driver
。该
--mount
标志允许您在创建卷之前指定卷的自定义元数据(“标签”)。当您使用
--mount
with时type=bind
,主机路径必须引用 主机上的现有路径。不会为您创建该路径,如果该路径不存在,服务将失败并出现错误。该
--mount
标志不允许您使用Z
或z
标志重新标记卷,这些标志用于selinux
标记。
使用命名卷创建服务
以下示例创建一个使用命名卷的服务:
$ docker service create \
--name my-service \
--replicas 3 \
--mount type=volume,source=my-volume,destination=/path/in/container,volume-label="color=red",volume-label="shape=round" \
nginx:alpine
对于服务的每个副本,引擎从部署任务的默认(“本地”)卷驱动程序请求名为“my-volume”的卷。如果该体积不存在,引擎将创建一个新体积并应用“颜色”和“形状”标签。
当任务启动时,卷将安装在/path/in/container/
容器内。
请注意,默认(“本地”)卷是本地范围的卷驱动程序。这意味着,根据任务的部署位置,该任务要么获取 名为“my-volume”的新卷,要么与同一服务的其他任务共享相同的“my-volume”。如果容器内运行的软件未设计为处理写入同一位置的并发进程,则多个容器写入单个共享卷可能会导致数据损坏。还要考虑到容器可以由 Swarm 编排器重新调度并部署在不同的节点上。
创建使用匿名卷的服务
以下命令创建一个具有三个副本且匿名卷位于 上的服务/path/in/container
:
$ docker service create \
--name my-service \
--replicas 3 \
--mount type=volume,destination=/path/in/container \
nginx:alpine
在此示例中,没有source
为卷指定名称 ( ),因此会为每个任务创建一个新卷。这保证了每个任务都有自己的卷,并且卷不会在任务之间共享。使用匿名卷的任务完成后将被删除。
创建使用绑定安装的主机目录的服务
/path/in/container
以下示例在支持服务的容器中绑定安装主机目录:
$ docker service create \
--name my-service \
--mount type=bind,source=/path/on/host,destination=/path/in/container \
nginx:alpine
设置服务模式(--mode)
服务模式决定这是复制服务还是全局 服务。复制服务运行指定数量的任务,而全局服务在集群中的每个活动节点上运行。
以下命令创建全局服务:
$ docker service create \
--name redis_2 \
--mode global \
redis:3.0.6
指定服务约束(--constraint)
您可以通过定义约束表达式来限制可调度任务的节点集。约束表达式可以使用匹配( ==
) 或排除( !=
) 规则。多个约束查找满足每个表达式(AND 匹配)的节点。约束可以匹配节点或 Docker 引擎标签,如下所示:
节点属性 | 火柴 | 例子 |
---|---|---|
node.id | 节点号 | node.id==2ivku8v2gvtg4 |
node.hostname | 节点主机名 | node.hostname!=node-2 |
node.role | 节点角色 ( manager / worker ) | node.role==manager |
node.platform.os | 节点操作系统 | node.platform.os==windows |
node.platform.arch | 节点架构 | node.platform.arch==x86_64 |
node.labels | 用户定义的节点标签 | node.labels.security==high |
engine.labels | Docker 引擎的标签 | engine.labels.operatingsystem==ubuntu-22.04 |
engine.labels
适用于 Docker Engine 标签,如操作系统、驱动程序等。Swarm 管理员node.labels
通过使用
docker node update
命令添加用于操作目的。
例如,以下将 redis 服务的任务限制为节点类型标签等于队列的节点:
$ docker service create \
--name redis_2 \
--constraint node.platform.os==linux \
--constraint node.labels.type==queue \
redis:3.0.6
如果服务约束排除集群中的所有节点,则会打印一条消息,指出找不到合适的节点,但调度程序将启动协调循环,并在合适的节点可用时部署服务。
在下面的示例中,未找到满足约束的节点,导致服务无法与所需状态协调:
$ docker service create \
--name web \
--constraint node.labels.region==east \
nginx:alpine
lx1wrhhpmbbu0wuk0ybws30bc
overall progress: 0 out of 1 tasks
1/1: no suitable node (scheduling constraints not satisfied on 5 nodes)
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
b6lww17hrr4e web replicated 0/1 nginx:alpine
region=east
将标签添加到集群中的节点后,服务将进行协调,并部署所需数量的副本:
$ docker node update --label-add region=east yswe2dm4c5fdgtsrli1e8ya5l
yswe2dm4c5fdgtsrli1e8ya5l
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
b6lww17hrr4e web replicated 1/1 nginx:alpine
指定服务放置首选项 (--placement-pref)
您可以设置服务将任务均匀地分配到不同类别的节点上。一个有用的例子是平衡一组数据中心或可用性区域上的任务。下面的例子说明了这一点:
$ docker service create \
--replicas 9 \
--name redis_2 \
--placement-pref spread=node.labels.datacenter \
redis:3.0.6
这--placement-pref
与spread
策略(当前唯一支持的策略)一起使用,将任务均匀地分布在节点标签的值上datacenter
。在此示例中,我们假设每个节点都附加了一个datacenter
节点标签。如果群中的节点之间存在该标签的三个不同值,则三分之一的任务将被放置在与每个值关联的节点上。即使具有一个值的节点多于另一个值,情况也是如此。例如,考虑以下节点集:
- 三个节点
node.labels.datacenter=east
- 两个节点
node.labels.datacenter=south
- 一个节点与
node.labels.datacenter=west
由于我们分布datacenter
标签的值并且服务有 9 个副本,因此每个数据中心最终将有 3 个副本。有三个节点与 value 关联east
,因此每个节点都会获得为此值保留的三个副本之一。有两个值为 的节点
south
,该值的三个副本将在它们之间分配,一个接收两个副本,另一个仅接收一个副本。最后,west
有一个节点将获得为 保留的所有三个副本west
。
如果某一类别中的节点(例如具有 的节点
node.labels.datacenter=south
)由于约束或资源限制而无法处理其公平份额的任务,则如果可能,额外的任务将分配给其他节点。
放置首选项支持引擎标签和节点标签。上面的示例使用节点标签,因为该标签是通过 引用的
node.labels.datacenter
。要分布引擎标签的值,请使用
--placement-pref spread=engine.labels.<labelname>
。
可以向服务添加多个放置首选项。这建立了偏好层次结构,以便任务首先划分为一个类别,然后进一步划分为其他类别。这可能有用的一个例子是在数据中心之间公平地划分任务,然后通过选择的机架划分每个数据中心内的任务。要添加多个放置首选项,请--placement-pref
多次指定该标志。顺序很重要,并且放置首选项将按照做出调度决策时给出的顺序应用。
以下示例设置具有多个放置首选项的服务。任务首先分布在各个数据中心,然后分布在机架上(如相应标签所示):
$ docker service create \
--replicas 9 \
--name redis_2 \
--placement-pref 'spread=node.labels.datacenter' \
--placement-pref 'spread=node.labels.rack' \
redis:3.0.6
使用 更新服务时docker service update
,--placement-pref-add
会在所有现有放置首选项之后附加新的放置首选项。
--placement-pref-rm
删除与参数匹配的现有放置首选项。
指定服务的内存要求和约束(--reserve-memory 和 --limit-memory)
如果您的服务需要最小量的内存才能正确运行,您可以使用 来--reserve-memory
指定该服务只能调度在具有这么多可用内存的节点上。如果没有满足条件的可用节点,则不会调度任务,而是保持挂起状态。
以下示例要求在安排服务在给定节点上运行之前,该节点上有 4GB 可用且可预留的内存。
$ docker service create --reserve-memory=4GB --name=too-big nginx:alpine
管理器不会在单个节点上调度一组容器,这些容器的组合预留超过该节点上的可用内存。
计划并运行任务后,--reserve-memory
不会强制执行内存限制。用于--limit-memory
确保任务使用的内存量不超过节点上给定的内存量。此示例将任务使用的内存量限制为 4GB。即使每个节点只有 2GB 内存,该任务也会被调度,因为这--limit-memory
是一个上限。
$ docker service create --limit-memory=4GB --name=too-big nginx:alpine
使用--reserve-memory
和 并--limit-memory
不能保证 Docker 不会在您的主机上使用比您想要的更多的内存。例如,您可以创建许多服务,其内存使用总和可能会耗尽可用内存。
您可以通过考虑主机上运行的其他(非容器化)软件来防止这种情况耗尽可用内存。如果
--reserve-memory
大于或等于--limit-memory
,Docker 将不会在没有足够内存的主机上调度服务。--limit-memory
将限制服务的内存保持在该限制内,因此如果每个服务都设置了内存预留和限制,则 Docker 服务将不太可能使主机饱和。其他直接在 Docker 主机上运行的非服务容器或应用程序仍然可能耗尽内存。
这种方法有一个缺点。保留内存还意味着您可能无法充分利用节点上的可用内存。考虑一个服务,在正常情况下使用 100MB 内存,但根据负载可能“峰值”为 500MB。为该服务保留 500MB(以保证可以为那些“峰值”保留 500MB)会导致大多数时间浪费 400MB 的内存。
简而言之,您可以采取更保守或更灵活的方法:
保守:预留500MB,限制在500MB。基本上,您现在将服务容器视为虚拟机,并且您可能会失go容器的一大优势,即每台主机的服务密度更高。
灵活:限制为 500MB,假设如果服务需要超过 500MB,则会发生故障。在 100MB“正常”要求和 500MB“峰值”要求之间预留一些容量”。这假设当该服务处于“峰值”时,其他服务或非容器工作负载可能不会出现。
您采取的方法在很大程度上取决于工作负载的内存使用模式。在决定采取某种方法之前,您应该在正常和峰值条件下进行测试。
cgroups
在 Linux 上,您还可以使用或其他相关操作系统工具在主机操作系统级别限制给定主机上服务的总体内存占用量。
指定每个节点的最大副本数 (--replicas-max-per-node)
使用该--replicas-max-per-node
标志设置可以在节点上运行的副本任务的最大数量。以下命令创建一个具有 2 个副本任务的 nginx 服务,但每个节点只有一个副本任务。
这可能有用的一个示例是平衡一组数据中心上的任务,并--placement-pref
让--replicas-max-per-node
设置确保副本在维护或数据中心故障期间不会迁移到另一个数据中心。
下面的例子说明了这一点:
$ docker service create \
--name nginx \
--replicas 2 \
--replicas-max-per-node 1 \
--placement-pref 'spread=node.labels.datacenter' \
nginx
将服务附加到现有网络 (--network)
您可以使用覆盖网络来连接群内的一项或多项服务。
首先,使用 docker network create 命令在管理器节点上创建覆盖网络:
$ docker network create --driver overlay my-network
etjpu59cykrptrgw0z0hk5snf
在集群模式下创建覆盖网络后,所有管理器节点都可以访问该网络。
当您创建服务并传递标志--network
以将服务附加到覆盖网络时:
$ docker service create \
--replicas 3 \
--network my-network \
--name my-web \
nginx
716thylsndqma81j6kkkb5aus
集群将 my-network 扩展到运行服务的每个节点。
同一网络上的容器可以使用服务发现来相互访问 。
长格式语法--network
允许指定别名和驱动程序选项列表:
--network name=my-network,alias=web1,driver-opt=field1=value1
将服务端口发布到 swarm 外部(-p, --publish)
您可以使用该标志发布服务端口,使它们在 swarm 外部可用--publish
。该--publish
标志可以采用两种不同风格的参数。简短版本是位置性的,允许您指定已发布的端口和目标端口,并用冒号 ( :
) 分隔。
$ docker service create --name my_web --replicas 3 --publish 8080:80 nginx
还有一种长格式,更易于阅读并允许您指定更多选项。首选长格式。使用短格式时,您无法指定服务的模式。以下是对与上述相同的服务使用长格式的示例:
$ docker service create --name my_web --replicas 3 --publish published=8080,target=80 nginx
您可以指定的选项有:
选项 | 简短语法 | 长语法 | 描述 |
---|---|---|---|
发布和目标端口 | --发布 8080:80 | --publish 已发布=8080,目标=80 | 容器内的目标端口以及使用路由网格 ( ingress ) 或主机级网络将其映射到节点上的端口。此表后面提供了更多选项。键值语法是首选,因为它在某种程度上是自记录的。 |
模式 | 无法使用短语法进行设置。 | --publish 发布=8080,目标=80,模式=主机 | 用于绑定端口的模式,可以是ingress或host。默认为入口以使用路由网格。 |
协议 | --发布 8080:80/tcp | --publish 发布=8080,目标=80,协议=tcp | 要使用的协议tcp、udp或sctp。默认为 tcp。要为两个协议绑定端口,请指定-p或 --publish标志两次。 |
当您使用模式发布服务端口时ingress
,群路由网格使该服务可以在每个节点上的已发布端口上进行访问,无论该节点上是否有正在运行的服务的任务。如果使用host
模式,则端口仅绑定在运行服务的节点上,并且节点上的给定端口只能绑定一次。您只能使用长语法设置发布模式。有关更多信息,请参阅
使用群模式路由网格。
提供托管服务帐户的凭据规范 (--credentials-spec)
此选项仅用于使用 Windows 容器的服务。必须
采用或 的
--credential-spec
格式。file://<filename>
registry://<value-name>
使用该file://<filename>
格式时,引用的文件必须存在于CredentialSpecs
docker 数据目录的子目录中,C:\ProgramData\Docker\
在 Windows 上默认为该子目录。例如,指定file://spec.json
负载C:\ProgramData\Docker\CredentialSpecs\spec.json
。
使用该registry://<value-name>
格式时,将从守护程序主机上的 Windows 注册表中读取凭据规范。指定的注册表值必须位于:
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs
使用模板创建服务
您可以使用 Go 的text/templateservice create
包提供的语法
对 的某些标志使用模板。
支持的标志如下:
--hostname
--mount
--env
下面列出了 Go 模板的有效占位符:
占位符 | 描述 |
---|---|
.服务.ID | 服务编号 |
。服务名称 | 服务名称 |
.服务.标签 | 服务标签 |
.节点ID | 节点号 |
.节点.主机名 | 节点主机名 |
.任务.ID | 任务编号 |
。任务名称 | 任务名称 |
.任务.槽位 | 任务槽位 |
模板示例
在此示例中,我们将根据服务名称、节点 ID 和所在主机名设置创建的容器的模板。
$ docker service create \
--name hosttempl \
--hostname="{{.Node.Hostname}}-{{.Node.ID}}-{{.Service.Name}}"\
busybox top
va8ew30grofhjoychbr6iot8c
$ docker service ps va8ew30grofhjoychbr6iot8c
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
wo41w8hg8qan hosttempl.1 busybox:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912 2e7a8a9c4da2 Running Running about a minute ago
$ docker inspect --format="{{.Config.Hostname}}" 2e7a8a9c4da2-wo41w8hg8qanxwjwsg4kxpprj-hosttempl
x3ti0erg11rjpg64m75kej2mz-hosttempl
在 Windows 上指定隔离模式 (--isolation)
默认情况下,在 Windows 节点上计划的任务使用为此特定节点配置的默认隔离模式运行。要强制使用特定的隔离模式,您可以使用该--isolation
标志:
$ docker service create --name myservice --isolation=process microsoft/nanoserver
Windows 上支持的隔离模式有:
default
:使用运行任务的节点上指定的默认设置process
:使用进程隔离(仅限Windows服务器)hyperv
:使用 Hyper-V 隔离
创建请求通用资源的服务 (--generic-resources)
您可以通过使用该标志来缩小任务可以登陆的节点类型
--generic-resource
(如果节点通告这些资源):
$ docker service create \
--name cuda \
--generic-resource "NVIDIA-GPU=2" \
--generic-resource "SSD=1" \
nvidia/cuda
把运行当作工作
作业是一种特殊的服务,旨在运行操作直至完成然后停止,而不是运行长时间运行的守护进程。当属于作业的任务成功退出(返回值0)时,该任务将被标记为“已完成”,并且不会再次运行。
作业通过使用两种模式之一启动,replicated-job
或者global-job
$ docker service create --name myjob \
--mode replicated-job \
bash "true"
该命令将运行一个任务,该任务将使用该bash
映像执行命令,true
该命令将返回 0,然后退出。
尽管乔布斯最终是一种不同类型的服务,但与其他服务相比,它们有一些注意事项:
- 所有更新或回滚配置选项均无效。作业可以更新,但无法推出或回滚,这使得这些配置选项毫无意义。
- 作业在到达该状态后永远不会重新启动
Complete
。这意味着对于作业,设置--restart-condition
为any
与设置为相同on-failure
。
作业可以在复制模式和全局模式下使用。
重复作业
复制的作业就像复制的服务。设置该--replicas
标志将指定要执行的作业的迭代总数。
默认情况下,复制作业的所有副本将立即启动。要控制任意时刻同时执行的副本总数,--max-concurrent
可以使用该标志:
$ docker service create \
--name mythrottledjob \
--mode replicated-job \
--replicas 10 \
--max-concurrent 2 \
bash "true"
上述命令将总共执行 10 个任务,但在任何给定时间只运行其中 2 个。
全球职位
全局作业类似于全局服务,任务在每个匹配放置约束的节点上执行一次。全球就业机会用众数表示global-job
。
请注意,创建全局作业后,添加到集群中的任何新节点都将在其上启动该作业中的任务。全局作业作为一个整体并不具有“完成”状态,除非满足作业约束的每个节点都有一个已完成的任务。