docker service create

描述建立新服務
用法docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]

Swarm 此命令適用於 Swarm 編排器。

描述

根據指定引數建立服務。

注意

這是一個叢集管理命令,必須在 Swarm 管理器節點上執行。要了解管理器和工作器,請參閱文件中的Swarm 模式部分

選項

選項預設值描述
--cap-addAPI 1.41+ 新增 Linux 能力
--cap-dropAPI 1.41+ 移除 Linux 能力
--configAPI 1.30+ 指定要暴露給服務的配置
--constraint放置約束
--container-label容器標籤
--credential-specAPI 1.29+ 用於託管服務帳戶的憑據規範(僅限 Windows)
-d, --detachAPI 1.29+ 立即退出,而不等待服務收斂
--dnsAPI 1.25+ 設定自定義 DNS 伺服器
--dns-optionAPI 1.25+ 設定 DNS 選項
--dns-searchAPI 1.25+ 設定自定義 DNS 搜尋域
--endpoint-modevip端點模式(vip 或 dnsrr)
--entrypoint覆蓋映象的預設 ENTRYPOINT
-e, --env設定環境變數
--env-file從檔案讀取環境變數
--generic-resource使用者定義資源
--groupAPI 1.25+ 為容器設定一個或多個補充使用者組
--health-cmdAPI 1.25+ 用於健康檢查的命令
--health-intervalAPI 1.25+ 執行檢查之間的時間(ms|s|m|h)
--health-retriesAPI 1.25+ 報告不健康所需的連續失敗次數
--health-start-intervalAPI 1.44+ 啟動期間執行檢查之間的時間(ms|s|m|h)
--health-start-periodAPI 1.29+ 容器在計入不穩定重試次數之前的啟動期(ms|s|m|h)
--health-timeoutAPI 1.25+ 允許一次檢查執行的最大時間(ms|s|m|h)
--hostAPI 1.25+ 設定一個或多個自定義主機到 IP 對映(host:ip)
--hostnameAPI 1.25+ 容器主機名
--initAPI 1.37+ 在每個服務容器內使用 init 來轉發訊號和回收程序
--isolationAPI 1.35+ 服務容器隔離模式
-l, --label服務標籤
--limit-cpu限制 CPU
--limit-memory限制記憶體
--limit-pidsAPI 1.41+ 限制最大程序數(預設 0 = 無限制)
--log-driver服務的日誌驅動程式
--log-opt日誌驅動程式選項
--max-concurrentAPI 1.41+ 併發執行的作業任務數(預設等於 --replicas)
--modereplicated服務模式(replicated, global, replicated-job, global-job
--mount將檔案系統掛載附加到服務
--name服務名稱
--network網路附件
--no-healthcheckAPI 1.25+ 停用任何容器指定的 HEALTHCHECK
--no-resolve-imageAPI 1.30+ 不查詢登錄檔以解析映象摘要和支援的平臺
--oom-score-adjAPI 1.46+ 調整主機的 OOM 偏好設定(-1000 到 1000)
--placement-prefAPI 1.28+ 新增放置偏好
-p, --publish將埠釋出為節點埠
-q, --quiet禁止進度輸出
--read-onlyAPI 1.28+ 將容器的根檔案系統掛載為只讀
--replicas任務數
--replicas-max-per-nodeAPI 1.40+ 每個節點的最大任務數(預設 0 = 無限制)
--reserve-cpu保留 CPU
--reserve-memory保留記憶體
--restart-condition滿足條件時重啟(none, on-failure, any)(預設 any
--restart-delay重啟嘗試之間的延遲(ns|us|ms|s|m|h)(預設 5s)
--restart-max-attempts放棄前最大重啟次數
--restart-window用於評估重啟策略的視窗(ns|us|ms|s|m|h)
--rollback-delayAPI 1.28+ 任務回滾之間的延遲(ns|us|ms|s|m|h)(預設 0s)
--rollback-failure-actionAPI 1.28+ 回滾失敗時的操作(pause, continue)(預設 pause
--rollback-max-failure-ratioAPI 1.28+ 回滾期間可容忍的失敗率(預設 0)
--rollback-monitorAPI 1.28+ 每個任務回滾後監控故障的持續時間(ns|us|ms|s|m|h)(預設 5s)
--rollback-orderAPI 1.29+ 回滾順序(start-first, stop-first)(預設 stop-first
--rollback-parallelism1API 1.28+ 同時回滾的最大任務數(0 表示一次性回滾所有任務)
--secretAPI 1.25+ 指定要暴露給服務的秘密
--stop-grace-period強制終止容器前的等待時間(ns|us|ms|s|m|h)(預設 10s)
--stop-signalAPI 1.28+ 停止容器的訊號
--sysctlAPI 1.40+ Sysctl 選項
-t, --ttyAPI 1.25+ 分配一個偽 TTY
--ulimitAPI 1.41+ Ulimit 選項
--update-delay更新之間的延遲(ns|us|ms|s|m|h)(預設 0s)
--update-failure-action更新失敗時的操作(pause, continue, rollback)(預設 pause
--update-max-failure-ratioAPI 1.25+ 更新期間可容忍的失敗率(預設 0)
--update-monitorAPI 1.25+ 每個任務更新後監控故障的持續時間(ns|us|ms|s|m|h)(預設 5s)
--update-orderAPI 1.29+ 更新順序(start-first, stop-first)(預設 stop-first
--update-parallelism1同時更新的最大任務數(0 表示一次性更新所有任務)
-u, --user使用者名稱或 UID (格式: <name|uid>[:<group|gid>])
--with-registry-auth將登錄檔身份驗證詳細資訊傳送給 Swarm 代理
-w, --workdir容器內的工作目錄

示例

建立服務

$ docker service create --name redis redis:7.4.1

dmu1ept4cxcfe8k8lhtux3ro3

$ docker service create --mode global --name redis2 redis:7.4.1

a8q9dasaafudfs8q8w32udass

$ docker service ls

ID            NAME    MODE        REPLICAS  IMAGE
dmu1ept4cxcf  redis   replicated  1/1       redis:7.4.1
a8q9dasaafud  redis2  global      1/1       redis:7.4.1

使用私有登錄檔上的映象建立服務(--with-registry-auth)

如果您的映象在需要登入的私有登錄檔上可用,請在登入後使用 `docker service create` 命令時帶上 `--with-registry-auth` 標誌。如果您的映象儲存在私有登錄檔 `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` 標誌為複製服務設定副本任務的數量。以下命令建立一個具有 5 個副本任務的 `redis` 服務:

$ docker service create --name redis --replicas=5 redis:7.4.1

4cdgfyky7ozwh3htjfw0d12qv

上述命令設定了服務的*期望*任務數。儘管命令會立即返回,但服務的實際擴充套件可能需要一些時間。`REPLICAS` 列顯示了服務的實際和期望副本任務數。

在以下示例中,期望狀態是 5 個副本,但當前 RUNNING 任務數為 3

$ docker service ls

ID            NAME   MODE        REPLICAS  IMAGE
4cdgfyky7ozw  redis  replicated  3/5       redis:7.4.1

一旦所有任務建立並 RUNNING,實際任務數就等於期望任務數。

$ docker service ls

ID            NAME   MODE        REPLICAS  IMAGE
4cdgfyky7ozw  redis  replicated  5/5       redis:7.4.1

建立帶有秘密的服務(--secret)

使用 `--secret` 標誌授予容器訪問 秘密 的許可權。

建立一個指定秘密的服務

$ docker service create --name redis --secret secret.json redis:7.4.1

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:7.4.1

4cdgfyky7ozwh3htjfw0d12qv

要授予服務訪問多個秘密的許可權,請使用多個 `--secret` 標誌。

如果未指定目標,則秘密位於容器中的 `/run/secrets`。如果未指定目標,則秘密的名稱用作容器中的記憶體檔案。如果指定了目標,則將其用作檔名。在上面的示例中,為每個指定的秘密目標建立了兩個檔案:`/run/secrets/ssh` 和 `/run/secrets/app`。

建立帶配置的服務(--config)

使用 `--config` 標誌授予容器訪問 配置 的許可權。

建立一個帶有配置的服務。配置將掛載到 `redis-config` 中,由在容器內部執行命令的使用者(通常是 `root`)擁有,檔案模式為 `0444` 或全域性可讀。您可以將 `uid` 和 `gid` 指定為數字 ID 或名稱。使用名稱時,提供的組/使用者名稱稱必須在容器中預先存在。`mode` 指定為 4 位數字序列,例如 `0755`。

$ docker service create --name=redis --config redis-conf redis:7.4.1

建立具有配置的服務並指定目標位置和檔案模式

$ docker service create --name redis \
  --config source=redis-conf,target=/etc/redis/redis.conf,mode=0400 redis:7.4.1

要授予服務訪問多個配置的許可權,請使用多個 `--config` 標誌。

如果未指定目標,則配置位於容器中的 `/`。如果未指定目標,則配置的名稱用作容器中檔案的名稱。如果指定了目標,則將其用作檔名。

建立一個具有滾動更新策略的服務

$ docker service create \
  --replicas 10 \
  --name redis \
  --update-delay 10s \
  --update-parallelism 2 \
  redis:7.4.1

當您執行 服務更新 時,排程程式一次最多更新 2 個任務,每次更新之間間隔 10s。有關更多資訊,請參閱 滾動更新教程

設定環境變數 (-e, --env)

這將為服務中的所有任務設定環境變數。例如:

$ docker service create \
  --name redis_2 \
  --replicas 5 \
  --env MYVAR=foo \
  redis:7.4.1

要指定多個環境變數,請指定多個 `--env` 標誌,每個標誌帶有一個單獨的鍵值對。

$ docker service create \
  --name redis_2 \
  --replicas 5 \
  --env MYVAR=foo \
  --env MYVAR2=bar \
  redis:7.4.1

建立具有特定主機名的服務 (--hostname)

此選項將 Docker 服務容器的主機名設定為特定字串。例如:

$ docker service create --name redis --hostname myredis redis:7.4.1

為服務設定元資料 (-l, --label)

標籤是一個 `key=value` 對,用於為服務應用元資料。為服務新增兩個標籤:

$ docker service create \
  --name redis_2 \
  --label com.example.foo="bar" \
  --label bar=baz \
  redis:7.4.1

有關標籤的更多資訊,請參閱應用自定義元資料

新增繫結掛載、卷或記憶體檔案系統 (--mount)

Docker 支援三種不同型別的掛載,允許容器從主機作業系統或記憶體檔案系統讀取或寫入檔案或目錄。這些型別是資料卷(通常簡稱為卷)、繫結掛載、tmpfs 和命名管道。

一個 **繫結掛載** 使主機上的檔案或目錄可供其掛載的容器使用。繫結掛載可以是隻讀或讀寫。例如,容器可以透過繫結掛載主機的 `/etc/resolv.conf` 來共享其主機的 DNS 資訊,或者容器可以將日誌寫入其主機的 `/var/log/myContainerLogs` 目錄。如果您使用繫結掛載,並且您的主機和容器對許可權、訪問控制或其他此類細節有不同的理解,您將遇到可移植性問題。

**命名卷** 是一種機制,用於將容器所需的持久資料與用於建立容器的映象和主機分離。命名卷由 Docker 建立和管理,即使沒有容器當前使用它,命名卷也會持久存在。命名卷中的資料可以在容器和主機之間以及多個容器之間共享。Docker 使用*卷驅動程式*來建立、管理和掛載卷。您可以使用 Docker 命令備份或恢復卷。

一個 **tmpfs** 在容器內掛載一個 tmpfs 用於易失性資料。

一個 **npipe** 將一個命名管道從主機掛載到容器中。

考慮這樣一種情況:您的映象啟動了一個輕量級 Web 伺服器。您可以使用該映象作為基礎映象,複製您的網站 HTML 檔案,並將其打包到另一個映象中。每次您的網站更改時,您都需要更新新映象並重新部署所有為您的網站提供服務的容器。更好的解決方案是將網站儲存在命名卷中,並在 Web 伺服器容器啟動時將其附加到每個容器。要更新網站,只需更新命名卷即可。

有關命名卷的更多資訊,請參閱資料卷

下表描述了適用於服務中繫結掛載和命名卷的選項:

選項必需描述
型別

掛載型別,可以是, 繫結, tmpfs,或命名管道。如果未指定型別,則預設為

  • :將託管卷掛載到容器中。
  • 繫結:將主機上的目錄或檔案繫結掛載到容器中。
  • tmpfs:在容器中掛載一個 tmpfs
  • 命名管道:將主機上的命名管道掛載到容器中(僅限 Windows 容器)。
srcsource對於type=bindtype=npipe
  • type=volume: src是指定卷名稱的可選方法(例如,src=my-volume)。如果命名的卷不存在,它將自動建立。如果未指定src,則卷將分配一個隨機名稱,該名稱在主機上保證唯一,但在叢集範圍內可能不唯一。隨機命名的卷與其容器具有相同的生命週期,並在容器銷燬時(即在service update或縮放或重新平衡服務時)銷燬。
  • type=bind: src是必需的,並指定要繫結掛載的檔案或目錄的絕對路徑(例如,src=/path/on/host/)。如果檔案或目錄不存在,則會產生錯誤。
  • type=tmpfs: src不支援。

dstdestinationtarget

容器內的掛載路徑,例如/some/path/in/container/。如果容器檔案系統中不存在該路徑,引擎將在掛載卷或繫結掛載之前在指定位置建立目錄。

readonlyro

引擎以讀寫方式掛載繫結和卷,除非在掛載繫結或卷時給定readonly選項。請注意,為繫結掛載設定readonly可能不會使其子掛載readonly,具體取決於核心版本。另請參閱bind-recursive.

  • true1或無值:以只讀方式掛載繫結或卷。
  • false0:以讀寫方式掛載繫結或卷。

繫結掛載選項

以下選項只能用於繫結掛載 (type=bind)

選項描述
繫結傳播

請參閱繫結傳播部分

一致性

掛載的一致性要求;以下之一

  • default:等同於consistent.
  • consistent:完全一致性。容器執行時和主機始終保持掛載的相同檢視。
  • 快取:主機的掛載檢視具有權威性。主機上進行的更新在容器內可見之前可能會有延遲。
  • 委派:容器執行時的掛載檢視具有權威性。在容器中進行的更新在主機上可見之前可能會有延遲。
bind-recursive預設情況下,子掛載也會遞迴繫結掛載。然而,當繫結掛載配置了readonly選項時,此行為可能會令人困惑,因為子掛載可能不會掛載為只讀,具體取決於核心版本。設定bind-recursive以控制遞迴繫結掛載的行為。

值是以下之一

  • <已啟用:啟用遞迴繫結掛載。如果核心是 v5.12 或更高版本,則只讀掛載會遞迴只讀。否則,它們不會遞迴只讀。
  • <已停用:停用遞迴繫結掛載。
  • <可寫:啟用遞迴繫結掛載。只讀掛載不會遞迴只讀。
  • <readonly:啟用遞迴繫結掛載。如果核心是 v5.12 或更高版本,則只讀掛載會遞迴只讀。否則,引擎會引發錯誤。
未指定選項時,預設行為對應於設定已啟用.
bind-nonrecursivebind-nonrecursive自 Docker Engine v25.0 起已棄用。請使用bind-recursive代替。

一個值是可選的

  • true1:等同於bind-recursive=disabled.
  • false0:等同於bind-recursive=enabled.
繫結傳播

繫結傳播是指在給定繫結掛載或命名卷中建立的掛載是否可以傳播到該掛載的副本。考慮掛載點 `/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)中已經存在檔案或目錄,則引擎會將這些檔案和目錄複製到卷中,允許主機訪問它們。設定卷不復制可停用將檔案從容器的檔案系統複製到卷並掛載空卷。

一個值是可選的

  • true1:如果您不提供值,則為預設值。停用複製。
  • false0:啟用複製。
卷選項特定於給定卷驅動程式的選項,在建立卷時將傳遞給驅動程式。選項以逗號分隔的鍵/值對列表形式提供,例如,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 標誌支援 docker run-v--volume 標誌支援的大部分選項,但有一些重要例外:

  • --mount 標誌允許您*每個卷*指定卷驅動程式和卷驅動程式選項,而無需提前建立卷。相比之下,docker run 允許您使用 --volume-driver 標誌指定一個由所有卷共享的單個卷驅動程式。

  • --mount 標誌允許您在卷建立之前為其指定自定義元資料(“標籤”)。

  • 當您將 `type=bind` 與 `--mount` 一起使用時,主機路徑必須指向主機上*現有*的路徑。該路徑不會為您建立,如果路徑不存在,服務將因錯誤而失敗。

  • --mount 標誌不允許您使用 Zz 標誌重新標記卷,這些標誌用於 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

對於服務的每個副本,引擎會向預設(“local”)卷驅動程式請求一個名為“my-volume”的卷,該卷部署在任務所在的節點上。如果該卷不存在,引擎會建立一個新卷並應用“color”和“shape”標籤。

任務啟動時,該卷會掛載到容器內的 `/path/in/container/`。

請注意,預設的(“local”)卷是一個本地範圍的卷驅動程式。這意味著,根據任務部署的位置,該任務會獲得一個名為“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)

服務模式決定這是*複製*服務還是*全域性*服務。複製服務執行指定數量的任務,而全域性服務在 Swarm 中的每個活動節點上執行。

以下命令建立一個全域性服務:

$ docker service create \
 --name redis_2 \
 --mode global \
 redis:7.4.1

指定服務約束(--constraint)

您可以透過定義約束表示式來限制任務可以排程到的節點集。約束表示式可以使用*匹配*(`==`)或*排除*(`!=`)規則。多個約束會找到滿足所有表示式(AND 匹配)的節點。約束可以匹配節點或 Docker Engine 標籤,如下所示:

節點屬性匹配示例
node.id節點 IDnode.id==2ivku8v2gvtg4
node.hostname節點主機名node.hostname!=node-2
node.role節點角色(manager/workernode.role==manager
node.platform.os節點作業系統node.platform.os==windows
node.platform.arch節點架構node.platform.arch==x86_64
node.labels使用者定義的節點標籤node.labels.security==high
engine.labelsDocker Engine 的標籤engine.labels.operatingsystem==ubuntu-24.04

engine.labels 適用於 Docker Engine 標籤,如作業系統、驅動程式等。Swarm 管理員透過使用 docker node update 命令新增 node.labels 用於操作目的。

例如,以下限制 redis 服務任務到節點型別標籤等於 queue 的節點:

$ docker service create \
  --name redis_2 \
  --constraint node.platform.os==linux \
  --constraint node.labels.type==queue \
  redis:7.4.1

如果服務約束排除了叢集中的所有節點,則會列印一條訊息,表明未找到合適的節點,但排程程式將啟動協調迴圈,並在合適的節點可用時部署服務。

在下面的示例中,未找到滿足約束的節點,導致服務未能與期望狀態協調:

$ 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:7.4.1

這使用 `spread` 策略(目前唯一支援的策略)的 `--placement-pref` 選項,將任務均勻地分佈到 `datacenter` 節點標籤的值上。在這個例子中,我們假設每個節點都附加了一個 `datacenter` 節點標籤。如果 Swarm 中的節點有三個不同的 `datacenter` 標籤值,那麼三分之一的任務將放置在與每個值相關聯的節點上。即使一個值比另一個值擁有更多的節點,這也是成立的。例如,考慮以下節點集:

  • 三個節點帶有 node.labels.datacenter=east
  • 兩個節點帶有 node.labels.datacenter=south
  • 一個節點帶有 node.labels.datacenter=west

由於我們正在根據 `datacenter` 標籤的值進行擴充套件,並且服務有 9 個副本,因此每個資料中心將最終分配 3 個副本。有三個節點與值 `east` 相關聯,因此每個節點將獲得為其保留的三個副本中的一個。有兩個節點帶有值 `south`,為其保留的三個副本將在它們之間分配,其中一個節點獲得兩個副本,另一個節點僅獲得一個。最後,`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:7.4.1

當使用 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。基本上,您現在將服務容器視為虛擬機器,並且您可能會失去容器的一大優勢,即每個主機的服務密度更高。

  • 靈活:限制為 500MB,假設如果服務需要超過 500MB,則表示其功能異常。保留介於 100MB“正常”需求和 500MB“峰值”需求之間的一些值。這假設當此服務處於“峰值”時,其他服務或非容器工作負載可能不會處於“峰值”。

您採取的方法很大程度上取決於您的工作負載的記憶體使用模式。您應該在正常和峰值條件下進行測試,然後才能確定一種方法。

在 Linux 上,您還可以使用 `cgroups` 或其他相關的作業系統工具,在主機作業系統級別限制服務在給定主機上的整體記憶體佔用。

指定每個節點的最大副本數 (--replicas-max-per-node)

使用 `--replicas-max-per-node` 標誌可設定可在節點上執行的最大副本任務數。以下命令建立一個 nginx 服務,該服務具有 2 個副本任務,但每個節點僅執行一個副本任務。

一個有用的示例是在資料中心集之間與 `--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)

您可以使用覆蓋網路來連線 swarm 中的一個或多個服務。

首先,在管理節點上使用 docker network create 命令建立一個覆蓋網路:

$ docker network create --driver overlay my-network

etjpu59cykrptrgw0z0hk5snf

在 Swarm 模式下建立覆蓋網路後,所有管理節點都可以訪問該網路。

當您建立服務並傳遞 `--network` 標誌以將服務附加到覆蓋網路時:

$ docker service create \
  --replicas 3 \
  --network my-network \
  --name my-web \
  nginx

716thylsndqma81j6kkkb5aus

Swarm 將 my-network 擴充套件到執行服務的每個節點。

同一網路上的容器可以使用服務發現相互訪問。

--network 的長格式語法允許指定別名列表和驅動程式選項:`--network name=my-network,alias=web1,driver-opt=field1=value1`

將服務埠外部發布到 Swarm (-p, --publish)

您可以使用 `--publish` 標誌將服務埠釋出到 Swarm 外部。`--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

您可以指定的選項有:

選項短語法長語法描述
釋出的埠和目標埠--publish 8080:80--publish published=8080,target=80

容器內的目標埠以及使用路由網格(入口)或主機級網路對映到節點上的埠。本表稍後提供更多選項。首選鍵值語法,因為它具有一定的自文件性。

mode短語法無法設定。--publish published=8080,target=80,mode=host

用於繫結埠的模式,可以是入口host。如果未指定型別,則預設為入口使用路由網格。

協議--publish 8080:80/tcp--publish published=8080,target=80,protocol=tcp

要使用的協議,tcp , udp,或sctp。如果未指定型別,則預設為tcp。要繫結兩個協議的埠,請指定-p--publish標誌兩次。

當您使用 `ingress` 模式釋出服務埠時,Swarm 路由網格使服務在每個節點上以釋出的埠可訪問,無論節點上是否有服務任務執行。如果您使用 `host` 模式,則埠僅繫結在執行服務的節點上,並且節點上的給定埠只能繫結一次。您只能使用長語法設定釋出模式。有關更多資訊,請參閱 使用 Swarm 模式路由網格

為託管服務帳戶提供憑據規範(--credentials-spec)

此選項僅用於使用 Windows 容器的服務。`--credential-spec` 必須採用 `file://` 或 `registry://` 格式。

使用 `file://` 格式時,引用的檔案必須存在於 docker 資料目錄的 `CredentialSpecs` 子目錄中,該目錄在 Windows 上預設為 `C:\ProgramData\Docker\`。例如,指定 `file://spec.json` 將載入 `C:\ProgramData\Docker\CredentialSpecs\spec.json`。

使用 `registry://` 格式時,憑據規範將從守護程式主機上的 Windows 登錄檔中讀取。指定的登錄檔值必須位於

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs

使用模板建立服務

您可以使用 Go 的 text/template 包提供的語法為 service create 的某些標誌使用模板。

支援的標誌如下:

  • --hostname
  • --mount
  • --env

Go 模板的有效佔位符如下所示

佔位符描述
.Service.ID服務 ID
.Service.Name服務名稱
.Service.Labels服務標籤
.Node.ID節點 ID
.Node.Hostname節點主機名
.Task.ID任務 ID
.Task.Name任務名稱
.Task.Slot任務插槽

模板示例

在此示例中,我們將根據服務的名稱、節點 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 Server)
  • 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-jobglobal-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` 模式表示。

請注意,在建立全域性作業後,新增到叢集的任何新節點都將啟動該作業中的一個任務。全域性作業作為一個整體沒有“完成”狀態,除非滿足作業約束的每個節點都有一個已完成的任務。