基本的docker使用參考:Docker 入門 到部署Web 程序- (阿里面試常用的docker命令和優點)
昨天去阿里面試 問我如果給你5台服務器 如何部署docker,我說一個個拷貝,面試官聽了臉都綠了,
說有沒有聽說過用swarm和compose 部署docker集群,我說沒用過,
后來回來一看自己的項目,我暈,每天用的yaml文件 就是 compose。
趕緊做一下總結:阿里的人喜歡讓你寫命令,比如 你是否記得 docker的部署命令啟動命令之類的:
5. 部署與維護
docker stack
部署命令:
docker stack deploy -c docker-compose.yml --with-registry-auth youclk,
私有倉庫必須加 --with-registry-auth
才能下載鏡像。除此之外常用的如下:
# network volume service secret 用法都類似,同出一系嘛...
docker stack ls
docker stack ps youclk
docker stack rm youclk
docker service
我使用 Compose 的場景一般都結合 Swarm,因此很少去記手動創建或者更改配置的命令了,意義也不大。除了查看移除等與上文相似以外,此處還應記兩個:
docker service logs --tail 10 youclk_proxy docker service update --force youclk_proxy
分別是查看日志和服務異常后強制重啟。
這是我的項目中用到的compose部署文件:manifest.yaml
version: v1 common: tools: oracle-jdk: 8 build: tools: maven: 3.3.3 run: workDir: ./ cmd: - sh deploy/compile.sh target: distDir: ./target/ files: - ./*.jar - ../deploy autodeploy: targetDir: /opt/meituan/com.sankuai.qcs.regulation.nanjingnew/ env: run: sh deploy/run.sh check: sh deploy/check.sh checkRetry: 3 #后面下掉,加默認值為1 CheckInterval: 20s #后面下掉
任何相對完整的應用服務都不可能是由單一的程序來完成支持,計划使用 Docker 來部署的服務更是如此。大型服務需要進行拆分,形成微服務集群方能增強其穩定性和可維護性。本篇隨筆將對 Docker Compose 和 Docker Swarm 的原理和配置做整理歸納,並分享其使用經驗。
總結一下,這張圖很形象:Docker 可以看做集裝箱把雜亂的貨物一個個整理歸類, Compose 則是用於編排這些集裝箱,最后 Swarm 就是多提供幾條船,掛掉一兩條還能繼續走,提高穩定性。
1. YAML 簡介
Docker Compose 的配置文件采用 YAML 格式,因此有必要在正文之前簡要說明下。YAML 是一門專門用來寫配置文件的語言,設計目標就是方便讀寫,其實質上是一種通用的數據串行化格式,基本語法規則如下:
- 大小寫敏感。
#
表示注釋。- 使用縮進表示層級關系。
- 縮進時不允許使用 Tab 鍵,只允許使用空格。
- 縮進的空格數目不重要,只要相同層級的元素左側對齊即可。
YAML 支持的數據結構有三種:
- 對象:
animal:cat
。 - 數組:一組中划線開頭的行,例如:
# ex1 - cat - dog - bird # ex2 - - cat - dog - bird # ex3 animal: [cat, dog, bird]
- 值類型和字符串。
2. Docker Compose
2.1 安裝與簡介
Docker 可以極為方便地部署單個服務,但這時候我們需要一個工具來整合 Docker 的功能,使之能夠更便捷地去管理整個微服務集群的部署和遷移,Docker Compose 正是應此而生。他是由 Python 編寫的程序,能夠根據指令結合配置文件轉換成對應的 Docker API 的操作,並直接體現到 Docker Daemon 中,這就代替我們完成了重復輸入復雜指令的過程,主要功能可分為以下兩點:
- Service:代表的是運行同種應用程序的一個或多個相同容器的抽象定義,也是我們在Docker Compose 中配置的主要對象。在每個 Docker Compose 的配置文件中,我們可以定義多個服務,並定義服務的配置,以及服務於服務之間的以來關系。
- Project:代表的是由多個服務所組成的一個相對完整的業務單元。
安裝命令:
curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose && chmod +x /usr/local/bin/docker-compose
2.2 配置參數
Docker Compose 的核心就是其配置文件,采用 YAML 格式,默認為 docker-compose.yml
,參數詳解可查閱“官方文檔”,以下只做一個常規摘要。
services
所有服務的根節點。
image
指定服務的鏡像名,若本地不存在,則 Compose 會去倉庫拉取這個鏡像:
services:
web:
image: nginx
ports
端口映射,例:
ports: - "80:80" - "81:81"
volumes
掛載主機目錄,其中 ro 表示只讀,例:
volumes: - "/etc/nginx/www:/www" - "/var/run/docker.sock:/tmp/docker.sock:ro"
大多數情況下集群中部署的應該都是無狀態服務,服務可復制且不固定在某一台宿主機,所以掛載的數據卷最好應當與宿主機脫離關系,例:
web: services: image: nginx volumes: - type: volume source: logs target: /mnt volume: nocopy: true volumes: logs: driver_opts: type: nfs o: addr=***.cn-hangzhou.nas.aliyuncs.com,rw device: ":/"
當然,這種情況下最好是優先創建數據卷,后在配置文件中引用,例:
docker volume create --driver local \ --opt type=nfs \ --opt o=addr=***.cn-hangzhou.nas.aliyuncs.com,rw \ --opt device=:/ \ logs volumes: logs: external: true
若必須掛載集群中一台宿主機的目錄作為數據卷,則要安裝一個 docker 插件:
docker plugin install vieux/sshfs # 若配置了密鑰對則可省略 password 參數 docker volume create \ -d vieux/sshfs \ --name sshvolume \ -o "sshcmd=user@1.2.3.4:/remote" \ -o "password=$(cat file_containing_password_for_remote_host)\ sshvolume
networks
配置服務間的網路互通與隔離,例:
services: web: image: nginx networks: - proxy - youclk networks: youclk: external: true proxy: external: true
secrets
配置服務密碼訪問,例:
services: redis: image: redis:latest deploy: replicas: 1 secrets: - my_secret - my_other_secret secrets: my_secret: file: "./my_secret.txt" my_other_secret: external: true docker secret create [OPTIONS] SECRET [file|-] echo "admin:password" | docker secret create my_secret - docker secret create my_secret ./secret.json
healthcheck
健康檢查,這個非常有必要,等服務准備好以后再上線,避免更新過程中出現短暫的無法訪問。
healthcheck: test: ["CMD", "curl", "-f", "http://localhost/alive"] interval: 5s timeout: 3s
其實大多數情況下健康檢查的規則都會寫在 Dockerfile 中:
FROM nginx RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/alive || exit 1
depends_on
依賴的服務,優先啟動,例:
depends_on:
- redis
environment & env_file
設置環境變量和指定環境變量的文件,例:
environment: - VIRTUAL_HOST=test.youclk.com env_file: - ./common.env
deploy
部署相關的配置都在這個節點下,例:
deploy: mode: replicated replicas: 2 restart_policy: condition: on-failure max_attempts: 3 update_config: delay: 5s order: start-first # 默認為 stop-first,推薦設置先啟動新服務再終止舊的 resources: limits: cpus: "0.50" memory: 1g deploy: mode: global # 不推薦全局模式(僅個人意見)。 placement: constraints: [node.role == manager]
若非特殊服務,以上各節點的配置能夠滿足大部分部署場景了。
3. Swarm
Docker 默認包含了 Swarm,因此可以直接使用,初始化命令:
docker swarm init
此時將會默認當前節點為 Leader,以下命令為查看 token:docker swarm join-token (worker|manager)
,其他節點可以用 manager 或者 worker 的身份加入到當前集群,例:
docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx 172.17.0.2:2377
執行 docker swarm leave
脫離集群。
以下各節點常規操作命令,比較簡單,就不解釋了:
docker node demote [NODE]
docker node inspect [NODE]
docker node ls
docker node promote [NODE]
docker node ps [NODE]
docker node rm [NODE]
docker node update [OPTIONS] NODE
4. 應用案例
集群最擅長的就是解決多服務問題,只要在同一 network 之下,服務之間默認可以直接通過 service_name 互通有無。但為了避免混亂,各服務與外部的通信最好統一交給一個反向代理服務轉發。因對 nginx 比較熟悉,所以我最初選擇的代理是“jwilder/nginx-proxy”:
server { listen 80; server_name localhost; location /alive { return 200; } } server { listen 81; return 301 https://$host$request_uri; } FROM jwilder/nginx-proxy ADD ./src /etc/nginx/conf.d ADD https://gitee.com/youclk/entry/raw/master/debian/sources-vpc.list /etc/apt/sources.list RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/alive || exit 1 version: "3.5" services: proxy: image: $REGISTRY/proxy ports: - "80:80" - "81:81" volumes: - "/var/run/docker.sock:/tmp/docker.sock:ro" deploy: placement: constraints: [node.role == manager] restart_policy: condition: on-failure max_attempts: 3 update_config: delay: 5s order: start-first resources: limits: cpus: "0.50" memory: 1g
負載均衡使用的是阿里雲的 SLB,監聽 80 -> 81, 443 -> 80
,這樣一個服務就實現了節點檢查、代理和 https 重定向為一身。拖 nginx 的福,反正用起來就是爽,點擊“Nginx 原理解析和配置摘要”進一步了解。
正所謂樂極生悲,某一次我在擴展 Swarm 集群的時候提升了部分 work 節點為 manager, 並且擴展了代理的數量,這讓很多服務頻繁出現 503,找來找去我發現問題出在 nginx-proxy 代理上。當服務在各節點分布不均的時候,非 leader 節點上的那個代理無法找到服務,廢了老大的勁兒也沒找到合理的解決方案。
最后我決定選擇“Docker Flow Proxy”作為新的代理(好家伙,這一看文檔嚇我一跳,我還是第一次看到私人的開源項目能把參考文檔寫得這么詳細,作者的細膩程度“令人發指”,小弟頂禮膜拜之),以下是我的案例:
version: "3.5" services: proxy: image: vfarcic/docker-flow-proxy ports: - "80:80" networks: - proxy environment: - LISTENER_ADDRESS=swarm-listener - MODE=swarm secrets: - dfp_users_admin deploy: replicas: 2 labels: - com.df.notify=true - com.df.port=8080 - com.df.serviceDomain=localhost - com.df.reqPathSearchReplace=/alive,/v1/docker-flow-proxy/ping swarm-listener: image: vfarcic/docker-flow-swarm-listener networks: - proxy volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - DF_NOTIFY_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure - DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove deploy: placement: constraints: [node.role == manager] networks: proxy: external: true secrets: dfp_users_admin: external: true
更換代理的過程也並非一帆風順,我在 https 重定向這個問題浪費了好多時間,最后也沒在代理中解決。作者當然是考慮到了這個問題,經典的解決方案應如下:
services: proxy: image: vfarcic/docker-flow-proxy ports: - "80:80" - "443:443" networks: - proxy environment: - LISTENER_ADDRESS=swarm-listener - MODE=swarm deploy: replicas: 2 labels: - com.df.notify=true - com.df.httpsOnly=true - com.df.httpsRedirectCode=301
但奈何哥哥“非經典”呀,我的 https 證書和負載均衡都委托給阿里雲的 SLB 了,SLB 代理的后端請求只能限定 http。我的想法還是監聽所有請求 443 端口的域名並返回 301,但以下方案並沒有成功:
labels: - com.df.notify=true - com.df.httpsRedirectCode=301 - com.df.serviceDomainAlgo=hdr_dom(host) - com.df.srcPort.1=80 - com.df.port.1=8080 - com.df.serviceDomain.1=localhost - com.df.reqPathSearchReplace.1=/alive,/v1/docker-flow-proxy/ping - com.df.srcPort.2=443 - com.df.port.2=8080 - com.df.serviceDomain.2=youclk.com,localhost - com.df.httpsOnly.2=true
當然重定向可以在各服務內部實現,但我不認為這是個好的解決方案。最后的最后,我想反正遲早都要上 CND,於是就在 CND 中加了 https 重定向(哎,就是帶寬的費用要 double 咯...):
除了代理,最好再加一個監控服務,我選擇了官方案例中的 visualizer ,配合 proxy 示例:
services: visualizer: image: dockersamples/visualizer networks: - proxy volumes: - "/var/run/docker.sock:/var/run/docker.sock" deploy: placement: constraints: [node.role == manager] labels: - com.df.notify=true - com.df.serviceDomain=visualizer.youclk.com - com.df.port=8080 - com.df.usersSecret=admin
visualizer 算是敏感服務了,一般需要用密碼保護,這里通過 com.df.usersSecret
指定了密碼文件,密碼已寫入 secrets dfp_users_admin
中。注意,com.df.usersSecret 的值與 dfp_users_* 必須相同,示例已在上文。部署后顯示如下:
docker-flow-proxy 還有一個默認的監控服務,顯示如下:
不過數據沒有統一收集,因此意義不大,看看就好。除此之外就是真正需要部署的應用了,只要服務器性能足夠,隨便想來幾個來幾個。
在之前使用Docker的過程中,一直是用 Docker run 命令單獨啟動container后再加入Overlay網絡的方式實現部署工作的. 這種方式看似直接,但是隨着服務所包含的container的個數越來越多(docker 命令)也就越來越多,由此帶來許多重復工作。。。
在官網上看到了通過 docker-compose 可以執行container的編排,尤其是compose files -- V3版本,加入的許多功能可以方便我們將服務中的contain部署在單獨的docker host 或者多個 hosts (swarm 節點) 上,於是考慮到目前對於 docker 的使用情況,確實也到了進行高級特性的嘗試階段,於是乎,走起!
分享一個示例:https://hackernoon.com/deploy-docker-compose-v3-to-swarm-mode-cluster-4159e9cca712#.lyx2e8fd9
上面的說的是如何使用compose V3 + swarm 構建一個貓狗投票系統,官方的例子,描述的很詳細,有興趣的童鞋可以研究一下。。。我在這里部署的方式也是使用了類似的方法,區別之處在與:實例中運用了“docker stack deploy”命令在多個host上面部署,而我使用的是“docker-compose up” 分別在兩個host上面啟動與部署服務。
准備工作
首先是通過 Swarm 創建 nodes,並且創建Overlay網絡模式. 我在這里就不在贅述,大家可以參看我之前的隨筆或者利用萬能的互聯網找到答案。
我這里使用的Docker engine 和 Docker-compose 版本如下:
Docker-compose
眾所周知,compose 就是 docker提供給我們用來進行編排的利器,那么我們應該如何使用她呢?
在解析docker-compose.yml之前,我想先說明一下我的業務,在熟悉業務之后,我們再來看看具體的"code".
業務需求:我們要在兩個host (swarm node)上面分別建立一組服務,為了簡單起見,我將nodes命名為nodeDB和nodeService;顧名思義,我們就是要在nodeDB上面建立database的服務(我這里是部署oracle server),在nodeService上面部署我們的程序(containers). 而 containers 之間的通信就是通過Swarm的Overlay網絡來完成的。
NodeDB的docker-compose.yml
version: '3' services: frs_orasvr: build: context: ./frsDB dockerfile: Dockerfile image: frs_orasvr_img:v1 container_name: frs_orasvr hostname: frs_orasvr ports: - "1521:1521" volumes: - /DATA/compose_frs/frsDB/cafisFRSDB/:/frs networks: - qrtSwamComposeNet networks: qrtSwamComposeNet: driver: overlay
這里請注意幾個內容:
1. networks: 在 compose file V3中, 允許我們通過networks關鍵字定義一個基於 Docker0 網絡的 subnet。 然后將我們的服務添加到這個subnet中。這樣做的好處實現了服務之間的隔離,一旦我們不需要這組服務了,我們可以通過命令“docker-compose down” 卸載服務和對應的subnet,他不會對其他的服務造成影響。
2. build: 我們可以通過build命令來指定加載那個Dockerfile。 Dockerfile 提供給我們一種方式將通用的dockr image 定制化成為自己的image,這些定制化的步驟就可以以Dockerfile的方式記錄下來。例如,我之前從docker 倉庫里pull 下來一個image, 我們叫他baseImage,之后在此基礎上進行了我的定制化生成myImage,如果需要在其他機器上面使用myImage,之前的做法吧myImage提交到私有倉庫,在需要的時候pull下來,但是如果不同的地方需要不同的myImage (v1,v2,v3...),就有可能造成Image泛濫。現在我們通過Dockerfile的方式記錄自己的定制過程,就會方便許多。
OK,啰嗦了一大堆。。。現在我們再來看看我們的Dockerfile長得如何:
FROM 172.100.1.15:5000/oracle11g_server_v3 RUN mkdir /frs/ COPY /cafisFRSDB/ /frs/ COPY /cafisFRSDB/listener.ora /app/oracle/11.2.0/network/admin/ CMD ["/bin/bash", "/frs/startup.sh"]
Dockerfile的內容很簡單,就是copy文件;
CMD -- 就是我們需要在啟動container的時候執行的shell腳本,通過她啟動oracle服務和實例(業務邏輯需求)。
現在我們cd到docker-compose.yml文件所在的目錄,輸入命令 “docker-compose up”,命令執行完成后我們可以看到
1. 建立網絡 composefrs_qrtSwarmComposeNet
2. 通過 Dockerfile 生成 imge
3. compose運行image,生成container並且調用shell腳本
到此,我們在nodeDB上面的工作就完成了。。。
NodeService的docker-compose.yml
我們要在這個host (swarm node) 部署服務,服務中的container需要與之前node上面oracle服務通信。。。
直接上code (簡單起見,只列出了services 中的一個 container)
version: '3' services: frs_ftsoft: build: context: ./ftsoft dockerfile: Dockerfile image: frs_ftsoft_img:v1 networks: - composefrs_qrtSwamComposeNet container_name: frs_ftsoft hostname: frs_ftsoft mac_address: xx:xx:xx:xx:xx:xx volumes: - /data/CabisSvr/DockerFrs/ftsoft:/frs networks: composefrs_qrtSwamComposeNet: external: true
Compose文件中使用的 Dockerfile 的內容和之前差不多,就不在這里多說了。
注意:
1. 由於之前我們在nodeDB的compose file 里面已經創建過了網絡,這里需要指定為external:true (不需要在創建了),在container里面加入即可。
2. 我們直接運行"docker-compose up"會報錯,內容大致為找不到指定的網絡。。。這是由於我們之前在nodeDB上面創建的network不會自動再新的node上面顯示(官方說法),所以我們需要先在 nodeService 上面運行一個container讓其加入網絡 “composefrs_qrtSwamComposeNet“
例如 “docker run -itd --name=mybusybox --network=composefrs_qrtSwamComposeNet busybox /bin/sh”
之后我們便可以在nodeService上面能夠查看到 composefrs_qrtSwamComposeNet 網絡,此時再運行“docker-compose up”就OK了。這點還是有點坑的
結論
OK,通過在nodeDB和nodeService上運行兩次 " docker-compose up ",命令,我們實現了在不同的hosts節點上運行containers,最終將他們以service的方式展現給外部用戶。
PS,我還嘗試過用docker stack deploy的方式進行部署,使用它最大的好處就是可以再一台機器上完成部署(傳說中的一鍵部署),但是由於其中的種種限制(例如必須保證需要部署的service中使用的image必須提前存在於指定機器或者私有倉庫,且不能使用Dockerfile臨時編譯; 不能指定conainer的IP,Mac 等等。。。),最終未能如願,希望在 docker 之后的版本里能夠改善吧。
本文只是一種實際部署方案的例子,涉及到的技術有(除Docker/Docker Swarm外):
Docker overlay network
Fluentd
Prometheus stack
vegasbrianc的Prometheus監控方案
步驟大綱:
部署Docker machine
基本配置
配置網絡
啟動Fluentd日志服務
部署Docker swarm集群
配置網絡
添加Node
部署Prometheus stack
給Node打Label
創建監控網絡
啟動service
部署應用
識別stateless與stateful
創建應用網絡
給Node打Label
啟動service
1 部署Docker machine 1.1 基本配置
准備若干Linux服務器(本例使用Ubuntu 16.04),參照Docker CE 鏡像源站提到的步驟安裝Docker CE。
參照Docker Daemon生產環境配置。
1.2 配置bridge網絡
參照Docker Daemon生產環境配置中的mtu和子網章節。
1.3 啟動Fluentd日志服務
參考使用Fluentd收集Docker容器日志。
2 部署Docker swarm集群
到一台機器上執行docker swarm init,這個機器將作為manager node。
執行docker node ls會看到類似下面的結果:
$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS dxn1zf6l61qsb1josjja83ngz * manager1 Ready Active Leader
如果你計划不會把工作負載跑在manager node上,那么使用docker drain:
docker node update --availability drain <node-id>
可參考Docker Swarm基本命令清單。
2.1 配置網絡MTU和子網
參考Docker Overlay網絡的MTU。
特別注意
觀察docker_gwbridge和ingress的子網是否與已有網絡沖突:
$ docker network inspect -f '{{json .IPAM}}' docker_gwbridge {"Driver":"default","Options":null,"Config":[{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1"}]} $ docker network inspect -f '{{json .IPAM}}' ingress {"Driver":"default","Options":null,"Config":[{"Subnet":"10.255.0.0/16","Gateway":"10.255.0.1"}]}
如果有沖突則參考Docker Overlay網絡的MTU中的方法修改子網。
2.2 添加Node
參考Docker Swarm基本命令清單。
3 部署Prometheus stack
使用的是vegasbrianc的Prometheus監控方案。
整個監控方案包含一下幾個組件:
Prometheus
Node-exporter,運行在每個node上
Alertmanager
cAdvisor,運行在每個node上
Grafana
3.1 給Node打Label
挑選一台Node作為運行監控服務的機器。給這個node打上label:
$ docker node update --label-add for-monitor-stack=1 <node-id>
3.2 創建監控網絡
$ docker network create -d overlay --attachable monitor-net
參考參考Docker Overlay網絡的MTU檢查子網與MTU是否配置正確。
3.3 啟動service
clone vegasbrianc的Prometheus監控方案 項目代碼。
使用我修改過的docker-stack.yml
啟動service:
$ docker stack deploy \ --with-registry-auth \ --prune \ -c docker-stack.yml \ p8s-monitor-stack
訪問地址:
Prometheus:http://<任意swarm node ip>:9000
Node-exporter:http://<任意swarm node ip>:9010
Alertmanager:http://<任意swarm node ip>:9020
cAdvisor:http://<任意swarm node ip>:9030
Grafana:http://<任意swarm node ip>:9040,用戶名admin,密碼foobar
4 部署應用 4.1 識別stateless與stateful
如果你的應用由多個組件(service)組成,那么在部署它們之前你得識別出哪些是stateless service哪些是stateful service。
針對每個service你自問以下三個問題:
這個service崩潰之后,是不是只需要重啟它就可以了,而不需要關心數據恢復?
這個service是否可以在node之間任意遷移,且不需要分布式存儲?
這個service是否無需固定IP?
如果上述回答都是Yes,那么這個service就是stateless的,只要有一個是No,則這個service是stateful的。
對於stateless service,你可以:
用docker stack deploy部署
用docker service create部署
對於stateful service,你可以:
用docker run部署
用docker-compose up部署
如果沒有固定IP的要求,那么你也可以用docker stack deploy/docker service create部署,前提是你得保證這個service只會固定在一台機器上運行。
有時候你的應用既有stateless service又有stateful service,這時需要把他們掛載到同一個overlay網絡里,這樣它們之間就能夠互相通信了。
4.2 創建應用網絡
創建app-net(你也可以改成自己的名字)
$ docker network create -d overlay --attachable app-net
參考Docker Overlay網絡的MTU檢查子網與MTU是否配置正確。
4.3 給Node打Label
如果你對於Service部署在哪個Node上有要求,那么你得給Node打上Label:
$ docker node update --label-add <your-label>=1 <node-id>
然后在docker-compose.yaml里添加約束條件:
version: "3.7" services: busybox: image: busybox deploy: placement: constraints: - node.labels.<your-label> == 1
4.4 啟動service
對於stateless service,編寫docker-compose.yaml,里面寫了同時掛載app-net和monitor-net,比如:
version: "3.7" services: busybox: image: busybox networks: app-net: monitor-net: aliases: - busybox ... networks: app-net: external: true monitor-net: external: true
注意上面設置了busybox service在monitor-net中的別名,這是因為如果你用docker stack deploy部署,那么busybox的名字默認是<stack-name>_busybox,這樣對於prometheus而言此名字不穩定,不便於配置詳見Prometehus監控Docker Swarm Overlay網絡中的容器。
然后用docker stack deploy部署:
$ docker stack deploy --with-registry-auth --prune -c docker-compose.yaml <stack-name>
如果用docker service create則:
$ docker service create \ --network app-net \ --network monitor-net \ --name <name> \ ... 其他參數 <image>
下面舉例docker run啟動stateful service的方法:
$ docker run -d \ --name <name> \ --network app-net \ ... 其他參數 \ <image> # 然后再掛載到monitor-net上 $ docker network connect monitor-net <name>