docker service create

說明建立新的服務
用法docker service create [選項] IMAGE [指令] [參數...]

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+ 執行檢查的間隔時間 (毫秒|秒|分|小時)
--health-retriesAPI 1.25+ 連續失敗次數達到此值時,回報服務不健康
--health-start-intervalAPI 1.44+ 在啟動期間執行檢查的間隔時間 (毫秒|秒|分|小時)
--health-start-periodAPI 1.29+ 容器啟動並初始化的期間,在此期間重試次數不計入不穩定狀態 (毫秒|秒|分|小時)
--health-timeoutAPI 1.25+ 允許單次檢查執行的最長時間 (毫秒|秒|分|小時)
--hostAPI 1.25+ 設定一或多個自定義主機到 IP 的映射 (主機: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+ 不要查詢 registry 以解析映像檔摘要和支援的平台
--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重新啟動嘗試之間的延遲 (奈秒|微秒|毫秒|秒|分|小時) (預設 5 秒)
--restart-max-attempts放棄前的最大重新啟動次數
--restart-window用於評估重新啟動策略的視窗 (奈秒|微秒|毫秒|秒|分|小時)
--rollback-delayAPI 1.28+ 任務回滾之間的延遲 (奈秒|微秒|毫秒|秒|分|小時) (預設 0 秒)
--rollback-failure-actionAPI 1.28+ 回滾失敗時的動作 (pause, continue) (預設 pause)
--rollback-max-failure-ratioAPI 1.28+ 回滾期間可容忍的失敗率 (預設 0)
--rollback-monitorAPI 1.28+ 每次任務回滾後監控失敗的持續時間 (奈秒|微秒|毫秒|秒|分|小時) (預設 5 秒)
--rollback-orderAPI 1.29+ 回滾順序 (start-first, stop-first) (預設 stop-first)
--rollback-parallelism1API 1.28+ 同時回滾的最大任務數 (0 表示一次全部回滾)
--secretAPI 1.25+ 指定要公開給服務的密鑰
--stop-grace-period強制關閉容器前的等待時間 (奈秒|微秒|毫秒|秒|分|小時) (預設 10 秒)
--stop-signalAPI 1.28+ 停止容器的訊號
--sysctlAPI 1.40+ Sysctl 選項
-t, --ttyAPI 1.25+ 分配一個偽終端 (pseudo-TTY)
--ulimitAPI 1.41+ Ulimit 選項
--update-delay更新之間的延遲 (奈秒|微秒|毫秒|秒|分|小時) (預設 0 秒)
--update-failure-action更新失敗時的動作 (pause, continue, rollback) (預設 pause)
--update-max-failure-ratioAPI 1.25+ 更新期間可容忍的失敗率 (預設 0)
--update-monitorAPI 1.25+ 每次任務更新後監控失敗的持續時間 (奈秒|微秒|毫秒|秒|分|小時) (預設 5 秒)
--update-orderAPI 1.29+ 更新順序 (start-first, stop-first) (預設 stop-first)
--update-parallelism1同時更新的最大任務數 (0 表示一次全部更新)
-u, --user使用者名稱或 UID (格式: <名稱|uid>[:<群組|gid>])
--with-registry-auth將 registry 驗證詳細資訊傳送至 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

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

如果您的映像檔位於需要登入的私有 registry 上,請在登入後,將 --with-registry-auth 旗標與 docker service create 搭配使用。如果您的映像檔儲存在私有 registry 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 節點。有了這些資訊,節點就能夠登入 registry 並提取映像檔。

建立具有 5 個副本任務的服務 (--replicas)

使用 --replicas 旗標設定副本服務的副本任務數量。以下命令建立一個具有 5 個副本任務的 redis 服務

$ 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 旗標,讓容器可以存取設定檔

使用設定檔建立服務。設定檔將會掛載到 redis-config,其擁有者為在容器內執行指令的使用者(通常是 root),且檔案模式為 0444 或可供所有人讀取。您可以將 uidgid 指定為數字 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 個任務,更新間隔為 10 秒。如需詳細資訊,請參閱滾動更新教學

設定環境變數 (-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 和命名管道。

**繫結掛載**會讓主機上的檔案或目錄可供掛載其中的容器使用。繫結掛載可以是唯讀或讀寫。例如,容器可以透過繫結掛載主機的 /etc/resolv.conf 來共用其主機的 DNS 資訊,或者容器可以將日誌寫入其主機的 /var/log/myContainerLogs 目錄。如果您使用繫結掛載,且您的主機和容器對權限、存取控制或其他此類細節有不同的概念,則會遇到可攜性問題。

**命名磁碟區**是一種將容器所需的持續性資料與用於建立容器的映像檔和主機電腦分離的機制。命名磁碟區由 Docker 建立和管理,即使目前沒有容器使用它,命名磁碟區仍然存在。命名磁碟區中的資料可以在容器和主機電腦之間共用,也可以在多個容器之間共用。Docker 使用**磁碟區驅動程式**來建立、管理和掛載磁碟區。您可以使用 Docker 指令備份或還原磁碟區。

**tmpfs** 會在容器內掛載 tmpfs 以用於揮發性資料。

**npipe** 會將主機上的命名管道掛載到容器中。

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

如需命名磁碟區的詳細資訊,請參閱資料磁碟區

下表描述適用於服務中繫結掛載和命名磁碟區的選項

選項必要說明
類型

掛載類型,可以是volume, bind, tmpfs,或npipe。如果未指定類型,則預設為volume

  • volume:將受管理的磁碟區掛載到容器中。
  • bind:將主機上的目錄或檔案繫結掛載到容器中。
  • tmpfs:在容器中掛載 tmpfs
  • npipe:將主機上的命名管道掛載到容器中(僅限 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:完全一致性。容器執行階段和主機始終保持掛載的相同視圖。
  • cached:主機的掛載視圖具有權威性。在主機上進行的更新在容器內顯示之前可能會有延遲。
  • delegated:容器執行階段的掛載視圖具有權威性。在容器中進行的更新在主機上顯示之前可能會有延遲。
bind-recursive預設情況下,子掛載也會遞迴地進行綁定掛載。但是,當綁定掛載使用readonly選項配置時,這種行為可能會造成混淆,因為子掛載可能不會掛載為唯讀,具體取決於內核版本。設定bind-recursive來控制遞迴綁定掛載的行為。

值可以是以下其中之一:

  • <enabled(啟用):啟用遞迴綁定掛載。如果內核版本為 v5.12 或更高版本,則唯讀掛載會遞迴地設為唯讀。否則,它們不會遞迴地設為唯讀。
  • <disabled(停用):停用遞迴綁定掛載。
  • <writable(可寫入):啟用遞迴綁定掛載。唯讀掛載不會遞迴地設為唯讀。
  • <readonly:啟用遞迴綁定掛載。如果內核版本為 v5.12 或更高版本,則唯讀掛載會遞迴地設為唯讀。否則,引擎會引發錯誤。
如果未指定選項,則預設行為對應於設定enabled(啟用).
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`**:與 shared 相同,但傳播也會延伸到任何原始或副本掛載點中巢狀的掛載點,以及從這些掛載點延伸。
  • **`rslave`**:與 `slave` 相同,但傳播也會延伸到任何原始或副本掛載點中巢狀的掛載點,以及從這些掛載點延伸。
  • **`rprivate`**:預設值。與 `private` 相同,表示原始或副本掛載點中任何位置的掛載點都不會朝任一方向傳播。

有關綁定傳播的更多資訊,請參閱 共享子樹的 Linux 內核文件

具名磁碟區的選項

以下選項僅能用於具名磁碟區 (`type=volume`)

選項說明
volume-driver

用於磁碟區的 volume-driver 外掛程式名稱。預設為"local",如果磁碟區不存在,則使用本地磁碟區驅動程式建立磁碟區。

volume-label要套用至建立時磁碟區的一個或多個自訂中繼資料(「標籤」)。例如,volume-label=mylabel=hello-world,my-other-label=hello-mars。有關標籤的更多資訊,請參閱套用自訂中繼資料
volume-nocopy預設情況下,如果您將空的磁碟區附加到容器,並且容器中的掛載路徑 (dst) 中已存在檔案或目錄,則引擎會將這些檔案和目錄複製到磁碟區中,允許主機存取它們。設定volume-nocopy停用將檔案從容器的檔案系統複製到磁碟區並掛載空磁碟區。

值是可選的

  • true1:如果您未提供值,則為預設值。停用複製。
  • false0:啟用複製。
volume-opt特定於給定磁碟區驅動程式的選項,在建立磁碟區時會傳遞給驅動程式。選項以逗號分隔的鍵/值對列表形式提供,例如,volume-opt=some-option=some-value,volume-opt=some-other-option=some-other-value。有關給定驅動程式的可用選項,請參閱該驅動程式的文件。

tmpfs 的選項

以下選項僅能用於 tmpfs 掛載 (`type=tmpfs`);

選項說明
tmpfs-sizetmpfs 掛載的大小,單位為位元組。在 Linux 中預設無限制。
tmpfs-modetmpfs 的檔案模式,以八進位制表示。(例如"700""0700"。)在 Linux 中預設為"1777"

「--mount」和「--volume」之間的差異

`--mount` 旗標支援 `docker run` 的 `-v` 或 `--volume` 旗標支援的大多數選項,但有一些重要的例外

  • `--mount` 旗標允許您*針對每個磁碟區*指定磁碟區驅動程式和磁碟區驅動程式選項,而無需事先建立磁碟區。相反,`docker run` 允許您使用 `--volume-driver` 旗標指定所有磁碟區共用的單個磁碟區驅動程式。

  • `--mount` 旗標允許您在建立磁碟區之前為磁碟區指定自訂中繼資料(「標籤」)。

  • 當您將 `--mount` 與 `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)

服務模式決定這是複本服務還是全域服務。複本服務會執行指定數量的任務,而全域服務則會在 swarm 中的每個作用中節點上執行。

以下指令會建立全域服務

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

指定服務限制 (--constraint)

您可以透過定義限制運算式來限制可以排程任務的節點集合。限制運算式可以使用相符 (==) 或排除 (!=) 規則。多個限制會尋找滿足每個運算式 (AND 相符) 的節點。限制可以如下方式比對節點或 Docker Engine 標籤

節點屬性相符項目範例
node.id節點 IDnode.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.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: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-prefspread 策略(目前唯一支援的策略)將任務平均分散到 datacenter 節點標籤的值上。在此範例中,我們假設每個節點都附加了 datacenter 節點標籤。如果 swarm 中節點之間有三個不同的標籤值,則三分之一的任務將放置在與每個值關聯的節點上。即使某個值的節點數量多於另一個值,也是如此。例如,請考慮以下節點集合

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

由於我們正在分散 datacenter 標籤的值,並且服務有 9 個複本,因此每個資料中心將會有 3 個複本。有三個節點與值 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。基本上,您現在將服務容器視為虛擬機,並且您可能會失去容器的一大優勢,即每個主機更高的服務密度。

  • **靈活**:限制為 500MB,假設如果服務需要超過 500MB,則表示它發生故障。在 100MB「正常」需求和 500MB「峰值」需求之間預留一些記憶體。這假設當此服務處於「峰值」時,其他服務或非容器工作負載可能不會處於峰值。

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

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

指定每個節點的最大副本數 (--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

將服務埠發佈到叢集外部 (-p, --publish)

您可以使用 --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

您可以指定的選項是

選項簡短語法長語法說明
發佈埠和目標埠--publish 8080:80--publish published=8080,target=80

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

模式無法使用簡短語法設定。--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 模式發佈服務埠時,叢集路由網格會使服務在每個節點上的已發佈埠上都可存取,無論節點上是否有該服務的任務正在執行。如果您使用 host 模式,則埠僅綁定在執行服務的節點上,並且節點上的指定埠只能綁定一次。您只能使用長語法設定發佈模式。如需更多資訊,請參閱使用叢集模式路由網格

提供受管服務帳戶的憑證規格 (--credentials-spec)

此選項僅用於使用 Windows 容器的服務。--credential-spec 必須採用 file://<filename>registry://<value-name> 的格式。

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

使用 registry://<value-name> 格式時,會從守護程式主機上的 Windows 登錄檔讀取憑證規格。指定的登錄檔值必須位於

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

使用範本建立服務

您可以使用 Go 的 text/template範本範例

在此範例中,我們將根據服務的名稱、節點的 ID 和它所在的主機名稱來設定所建立容器的範本。

在 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-jobglobal-job

$ docker service create --name myjob \
                        --mode replicated-job \
                        bash "true"

此命令將運行一個任務,該任務將使用 bash 映像執行命令 true,該命令將返回 0 然後退出。

雖然作業最終是不同類型的服務,但與其他服務相比,它們有一些需要注意的地方

  • 所有更新或回滾配置選項均無效。作業可以更新,但不能逐步推出或回滾,因此這些配置選項無關緊要。
  • 作業在達到「完成」狀態後永遠不會重新啟動。這表示對於作業,將 --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 表示。

請注意,在建立全域作業後,在添加到叢集的任何新節點上都會啟動該作業的任務。全域作業整體上沒有「完成」狀態,除非每個符合作業條件約束的節點都有一個已完成的任務。