今天要為應用程式新增其他服務,使其功能更為完整。在 Get Started
中這是第三層,稱為堆疊 (stack)。堆疊是一組彼此相關的服務,共享相依性,並且可以一起被編配 (orchestrated) 及擴展 (scaled)。大部分的概念及工具前兩天都介紹過了,那就直接開始吧。因為這個服務還是要部署在 swarm cluster 中,請先將昨天的虛擬機啟動,並組成具有一 manager 及一 worker 的 swarm cluster。
首先編輯 docker-compose.yml
,內容如下,主要是加上一個服務稱為 visualizer
,它會在網頁介面上顯示 swarm 如何安排這些容器。
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
restart_policy:
condition: on-failure
resources:
limits:
cpus: "0.1"
memory: 50M
ports:
- "80:80"
networks:
- webnet
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
- webnet
networks:
webnet:
請將第 5 行的 username/repo:tag
置換成上傳至 Docker Hub 的映像檔位置,而原本 web
服務的 ports 設定的值改為 "80:80"
,表示服務的 80 port 會對應本機的 80 port,之後可以直接以 80 port 而不是先前的 4000 port 來連接 web
服務。在 visualizer
中有兩個新的設定之前沒看過,第一個是 volumes,讓容器可以存取本機的 socket 檔案,第二個是 placement
的 constraints
,確保 visualizer
這個服務只會運行在 manager
節點,這是因為 swarm manager 才能知道這個 swarm 中各個節點的狀況。visualizer
服務使用的映像檔可直接由 Docker Hub 取得。
接下來設定 shell 讓它可直接與 swarm manager 溝通,指令是 eval $(docker-machine env myvm1)
,並部署新的應用程式,指令是 docker stack deploy -c docker-composer.yml getstartedlab
。用 docker stack ls
及 docker service ls
分別列出目前的堆疊和服務項目:
$ docker stack ls
NAME SERVICES ORCHESTRATOR
getstartedlab 2 Swarm
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
o2yy2v16xzsq getstartedlab_visualizer replicated 1/1 dockersamples/visualizer:stable *:8080->8080/tcp
wea9mjlcdhw1 getstartedlab_web replicated 5/5 odie1111/get-started:part2 *:80->80/tcp
可看到這個應用程式目前有兩個服務及它們的 ID、名稱、replica 數量等資訊。接下來以瀏覽器連至任一節點的 8080 port,看看新添加的服務頁面是如何呈現的。
可看出 swarm 有兩個節點,各有三個 task。其中 getstartedlab_visualizer
是新加入的服務,只有一個 task,位於 swarm manager 上,正如在 docker-composer.yml
中設置的一樣。而這個服務雖然只部署於 swarm manager 上,但透過兩個節點的 IP 都可以連接至它。
visualizer
這個服務和 web
並不具相依性,現在要再加入一個服務,它和 web
服務具相依性,是 web
後端的資料庫,用來提供計數,同時也透過這個資料庫服務,示範如何在 Docker 中留存資料。
首先在 docker-compose.yml
中加入新的服務 redis
,設定檔片段如下:
redis:
image: redis
ports:
- "6379:6379"
volumes:
- "/home/docker/data:/data"
deploy:
placement:
constraints: [node.role == manager]
command: redis-server --appendonly yes
networks:
- webnet
將以上片段放在 services
段落中,visualizer
的後面,請留意縮排。文件中指出 Redis 的官方映像檔有被授權可以使用 redis
這個名稱,因此不需使用 username/repository
這樣的格式,和之前使用過的 hello-world
映像檔情況類似。接下來關於如何留存 redis
服務中的資料,有幾個重要的關鍵,第一個是讓 redis
只在同一台機器上運作,以存取相同的檔案系統,第二個是讓 redis
能存取主機中的某一目錄,並將它對應到容器中的 /data
目錄,這是 Redis 儲存資料的地方。command
是指容器運行後要執行的指令,這裡會啟動 Redis server。
接下來準備部署應用程式,先在 myvm1
中建立 /home/docker/data
目錄,以作為 Redis 儲存資料之用。雖然已經設定過 shell 讓 docker 可以直接和 myvm1
溝通,但建立目錄並非 docker 指令,所以要用 docker-machine ssh
連到 myvm1
來做,登入後的工作目錄即是 /home/docker
,因此直接使用指令 docker-machine ssh myvm1 "mkdir data"
來建立 myvm1
中的目錄。
現在可以用指令 docker stack deploy -c docker-compose.yml getstartedlab
來部署或更新應用程式,如果原本應用程式就已經在執行,docker stack deploy
會直接把 redis
服務加入應用程式,不會感受到應用程式的 downtime。(但如果是更新 docker-compose.yml
,刪除 redis
服務,docker stack deploy
並不會將 redis
服務停止。)
以瀏覽器連接節點的 80 port,會發現頁面上的計數 Visits 欄位開始更新;連接節點 8080 port 可看見目前的 swarm 服務的狀況,visualizer
和 redis
兩個服務都只在 manager 上運行。
要確認 Redis 資料是否留存,可將應用程式卸除後再重新部署,並確認是否延續上次的計數,或者可試驗將 volumes 設定刪除,此時計數應該會重新開始。
以上就是 Get Started
關於服務堆疊的部分,這裡示範了在 swarm 節點部署具多個服務且有相依性的應用程式,並以 volumes 來留存 docker 中的資料。Get Started
還有一個部署到雲端環境的教學,這裡暫時先跳過,有興趣的夥伴再自己參考文件操作看看吧。