本篇教程會介紹如何使用docker swarm
進行容器的編排與分發friendlyhello:v4,這一服務可以通過瀏覽器訪問,獲取當前節點的Hostname,最終效果如下:
STEP 1: 創建虛擬機
爲了模擬集羣環境,我們創建3個虛擬機,1個作爲manager節點、另外2個則是worker節點,我自己的mac是8g內存,雖然有些捉急,但3個vm還是撐得住的:
$ docker-machine create manager
$ docker-machine create worker-1
$ docker-machine create worker-2
然後分別進入這三臺虛擬機(請開三個terminal來操作):
$ docker-machine ssh manager
$ docker-machine ssh worker-1
$ docker-machine ssh worker-2
STEP 2: 初始化集羣
首先確認一下每個vm的IP:
$ ifconfig
例如,我現在三個ip分別是:
- manager: 192.168.99.112
- worker-1: 192.168.99.113
- worker-2: 192.168.99.114
然後在manager
裏,執行:
$ docker swarm init --addvertise-addr <你的manager節點的ip>
# 我自己的命令:
$ docker swarm init --addvertise-addr 192.168.99.112
完成後,複製輸出的加入swarm集羣的命令
,在兩個worker裏分別執行一下,最後效果如下就說明成功了:
STEP 3: 創建friendlyhello:v4
服務
我們先在當前目錄下直接創建兩個文件,app.py
Dockerfile
,並加入如下代碼:
-
app.py
from flask import Flask from redis import Redis, RedisError import os import socket # Connect to Redis redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2) app = Flask(__name__) @app.route("/") def hello(): try: visits = redis.incr("counter") except RedisError: visits = "<i>cannot connect to Redis, counter disabled</i>" html = "<b>HostName:</b> {host_name}<br/>" \ "<b>Hostname:</b> {hostname}<br/>" \ "<b>Visits:</b> {visits}" return html.format(host_name=os.getenv("HOSTNAME", "UNKNOWN"), hostname=socket.gethostname(), visits=visits) if __name__ == "__main__": app.run(host='0.0.0.0', port=5000)
-
Dockerfile
FROM python:3.7-slim WORKDIR /app COPY . /app RUN pip install flask redis -i https://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com EXPOSE 5000 CMD ["python", "app.py"]
接着構建image
:
$ docker build -t friendlyhello:v4 .
然後通過docker service create
來創建服務,--replicas 3
參數表示創建3個副本:
$ docker service create --replicas 3 -p 5000:5000 --name friendly friendlyhello:v4
成功以後,我們就可以看到這一服務的task
們了:
$ docker service ps friendly
但是,我們發現只有manager
節點的task
啓動了,2個worker
節點都表示沒有鏡像,所以接下來我們就需要去做分發。
STEP 4: 快速分發鏡像到所有節點
我們先縮個容:
$ docker service scale friendly=1
爲了高效分發,我們不用docker hub
,而是自己部署一個registry
服務:
$ docker service create --name registry --publish 5555:5000 registry:2
看看成功了沒:
$ docker service ps registry
OK,接下來我們來把friendlyhello:v4
鏡像給推送到registry
,在此之前,我們先創建一個配置文件,加入配置,否則可能會出現https
相關問題:
$ vi /etc/docker/daemon.json
寫入:
{"insecure-registries": ["<你的manager的ip>:5555"]}
// 我的配置:
{"insecure-registries": ["192.168.99.112:555"]}
接着重啓一下docker:
$ sudo /etc/init.d/docker restart
重啓後,我們就可以重新打tag
然後push
到registry
了:
$ docker tag friendlyhello:v4 <你的manager的ip>:5555/friendlyhello:v4
$ docker push <你的manager的ip>:5555/friendlyhello:v4
# 我的命令:
$ docker tag friendlyhello:v4 192.168.99.112:5555/friendlyhello:v4
$ docker push 192.168.99.112:5555/friendlyhello:v4
如果這裏出現了奇奇怪怪的問題,試試等個幾秒重新執行一下
接着,分別到worker-1
和worker-2
裏,加入一個一樣的daemon.json:
$ vi /etc/docker/daemon.json
別忘了添加完配置後重啓一下
重啓後,就可以pull
下我們需要的那個鏡像了:
$ docker pull 192.168.99.112:5555/friendlyhello:v4
$ docker tag 192.168.99.112:5555/friendlyhello:v4 friendlyhello:v4
如果又出現了奇奇怪怪的問題,可以試試在manager
節點再重新push
一下
接着在manager
節點擴容:
$ docker service scale friendly=3
這下3個節點的task
就都成功跑起來了:
$ docker service ps friendly
可以通過瀏覽器訪問看看:
部署是沒什麼問題了,不過我們還需要讓它顯示所使用的node的名字,這需要加入環境變量。
我們先關了現在的服務:
$ docker service rm friendly
再重新創建,同時加入新的參數:
$ docker service create --replicas 3 -p 5000:5000 --name friendly3 -e HOSTNAME="{{.Node.Hostname}}" --hostname="{{.Node.Hostname}}-{{.Node.ID}}-{{.Service.Name}}" friendlyhello:v4
再來訪問看看:
STEP 5: 用Portainer可視化管理Swarm集羣
回到manager
節點,現在來通過docker stack
部署Portainer
:
$ curl -L https://downloads.portainer.io/portainer-agent-stack.yml -o portainer-agent-stack.yml
$ docker stack deploy --compose-file=portainer-agent-stack.yml portainer
完成後,我們可以通過:9000
端口來訪問Portainer
:
這裏有豐富的功能,可以方便我們可視化地操作swarm集羣