從零開始,使用Docker Swarm部署集群教程


 

本文首先從Dockerfile創建了一個簡單web鏡像

然后將web鏡像推送到了遠程倉庫,以備后面集群中不同機器自動下載

之后使用docker-compose.yml配置了一個應用

而后新建了2台虛擬機作為swarm節點,並部署應用的5個實例在這兩台虛擬機上

最后還講了如何如果更改集群配置、如何擴容您的集群和如重新發布您的應用

一、創建一個簡單web鏡像,並推送到docker倉庫

1、創建Dockerfile

創建一個空目錄, 然后CD到新目錄,創建名為Dockerfile的文件,將以下內容復制並粘貼到該文件中,然后保存。 注意Dockerfile中每個語句的注釋。

# Use an official Python runtime as a parent image FROM python:2.7-slim # Set the working directory to /app WORKDIR /app # Copy the current directory contents into the container at /app ADD . /app # Install any needed packages specified in requirements.txt RUN pip install --trusted-host pypi.python.org -r requirements.txt # Make port 80 available to the world outside this container EXPOSE 80 # Define environment variable ENV NAME World # Run app.py when the container launches CMD ["python", "app.py"]

這個Dockerfile使用了我們尚未創建的幾個文件,即app.py和requirements.txt。 下面讓我們創建他們。

我們的贏

2、創建應用程序

再創建兩個文件,requirements.txt和app.py,並將它們與Dockerfile放在同一個文件夾中。 至此完成了我們的應用程序,您可以看到它非常簡單。 當上面的Dockerfile構建成鏡像后,由於Dockerfile的ADD命令,app.py和requirements.txt將會被加入到鏡像中,並且由於EXPOSE命令暴露了80端口,我們可以通過HTTP訪問app.py的輸出。

requirements.txt

Flask
Redis

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 = "<h3>Hello {name}!</h3>" \ "<b>Hostname:</b> {hostname}<br/>" \ "<b>Visits:</b> {visits}" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits) if __name__ == "__main__": app.run(host='0.0.0.0', port=80)

3、構建鏡像

我們准備構建應用程序。 確保您仍處於創建的目錄的頂層。 這是ls應該顯示的內容:

$ ls
Dockerfile		app.py			requirements.txt

現在運行build命令。 這將創建一個Docker鏡像,我們使用-t為它取了一個友好的名稱。

$ docker image ls

REPOSITORY            TAG                 IMAGE ID
friendlyhello         latest              326387cea398

4、運行應用

運行應用程序,使用-p將計算機的端口4000映射到容器的已發布端口80:

docker run -p 4000:80 friendlyhello

您應該在http://0.0.0.0:80看到Python正在為您的應用程序提供服務的消息。 但是該消息來自容器內部,它不知道您將該容器的端口80映射到4000,從而生成正確的URL http:// localhost:4000。

在Web瀏覽器中轉到該URL,以查看在網頁上提供的顯示內容。

您還可以在shell中使用curl命令來查看相同的內容。

$ curl http://localhost:4000

<h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter disabled</i>

到此鏡像創建完成,當然你也可以使用自己的其它web鏡像

5、推送鏡像到遠程倉庫

1、首先到https://hub.docker.com/注冊一個賬號,保存下用戶名密碼

2、控制台登陸dockerhub賬戶

$ docker login
    輸入剛注冊的用戶名密碼

3、查看鏡像

$ docker image ls

REPOSITORY            TAG                 IMAGE ID
friendlyhello         latest              326387cea398

3、選擇需要上傳的鏡像,重命名為指定的格式

$ docker  tag friendlyhello abs52121/friendlyhello:v1
abs52121:為我自己的dockerhub賬戶名稱,替換成你剛注冊的名稱

friendlyhello:為自己為鏡像取的名字

v1:為任意設置的版本號

4、完成上述操作后,即可提交鏡像到自己的倉庫

$ docker push abs52121/friendlyhello:v1

二、創建docker-compose.yml文件

docker-compose.yml文件是一個YAML文件,用於定義Docker容器在生產中的行為方式。

將下面內容保存為docker-compose.yml, 確保已將第一部分中創建的鏡像推送到遠程倉庫,並將username/repo:tag替換為你自己的鏡像信息。

version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: username/repo:tag
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:

這個docker-compose.yml文件告訴Docker執行以下操作:

從注冊中心中提取我們在步驟1中上傳的鏡像。

從此鏡像運行5個實例作為一個服務,服務名為web,限制每個實例使用最多10%的CPU(所有核心)和50MB的RAM。

如果如果容器出錯,立即重啟。

將主機上的端口4000映射到Web的端口80。

指示Web容器通過稱為webnet的負載平衡網絡共享端口80。 (在內部,容器發布在web的80端口)

默認使用Webnet網絡(負載平衡網絡)。

三、運行你的帶負載均衡集群應用

1、初始化swarm

$ docker swarm init

2、現在讓我們來運行吧,您需要為您的應用程序命名,在這里它被設置為getstartedlab:

$ docker stack deploy -c docker-compose.yml getstartedlab

3、我們的單個服務在一台主機上運行已部署5個容器實例, 讓我們來看一下吧。

$ docker service ls 
s31sqx0dmkdh        getstartedlab_web          replicated          5/5                 abs52121/friendlyhello:v1         *:80->80/tcp


$ docker service ps getstartedlab_web
ID                  NAME                  IMAGE                       NODE                    DESIRED STATE       CURRENT STATE                ERROR               PORTS
rzk868yrs1zm        getstartedlab_web.1   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago
tmp93inu2bu9        getstartedlab_web.2   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago
jeasl6c1pah1        getstartedlab_web.3   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago
ik2wb1986qxf        getstartedlab_web.4   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago
s3dgi0lr7clf        getstartedlab_web.5   abs52121/friendlyhello:v1   linuxkit-025000000001   Running             Running about a minute ago

#查看所有容器id $ docker container ls -q

4、您可以連續多次運行curl -4 http://localhost:4000,或者在瀏覽器中轉到該URL並點擊刷新幾次。

無論哪種方式,容器ID都會發生變化,從而證明負載均衡; 對於每個請求,以循環方式選擇5個任務中的一個來響應。 容器ID與上一個命令(docker container ls -q)的輸出匹配。

5、擴展你的應用

您可以通過更改docker-compose.yml文件,並重新運行docker stack deploy命令來擴展應用程序:

$ docker stack deploy -c docker-compose.yml getstartedlab

Docker執行就地更新,無需殺死任何容器。

現在,重新運行docker container ls -q以查看已重新配置的已部署實例。 如果增加副本數量,則會啟動更多任務,從而啟動更多容器。

6、退出應用程序和swarm

通過 docker stack rm退出程序:

$ docker stack rm getstartedlab

退出swarm

$ docker swarm leave --force

7、了解Swarm集群
swarm是一組運行Docker並加入群集的計算機。在此之后,您繼續運行您習慣使用的Docker命令,但現在它們由群集管理器在群集上執行。集群中的機器可以是物理的或虛擬的。加入swarm后,它們被稱為節點。

Swarm 管理器可以使用多種策略來運行容器,例如“emptiest node”  - 它使用容器填充利用率最低的機器。或“global”,它確保每台機器只獲得指定容器的一個實例。您可以指示swarm管理器在Compose文件中使用這些策略,就像您上面已經使用的那樣。

Swarm 管理器是群中唯一可以執行命令的機器,或授權其他機器作為工作者加入群集。工作者只是在那里提供能力,並且沒有權力告訴任何其他機器它能做什么和不能做什么。

到目前為止,您一直在本地計算機上以單主機模式使用Docker。但是Docker也可以切換到swarm模式,這就是使用群集的能力。立即啟用群集模式使當前計算機成為swarm管理器(swarm init命令)。之后,Docker就會運行您在管理的swarm上執行的命令,而不僅僅是在當前機器上。

四、在不同的機器上運行你的集群應用

1、首先通過docker-machine創建2個虛擬機(當然也可以使用你目前已經有的物理機或者虛擬機)

現在使用docker-machine創建幾個VM,使用VirtualBox驅動程序,在運行命令前請確保你安裝了virtualbox虛擬機:

$ docker-machine create --driver virtualbox myvm1
$ docker-machine create --driver virtualbox myvm2

牆內用戶可以自行百度下載boot2docker.iso 文件,並使用--virtualbox-boot2docker-url參數指定文件位置

$ python-docker huhaichao$ docker-machine create --driver virtualbox --virtualbox-boot2docker-url=/path/to/boot2docker.iso myvm3

2、您現在創建了兩個名為myvm1和myvm2的VM。

使用此命令列出計算機並獲取其IP地址。

$ docker-machine ls
NAME    ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER        ERRORS
myvm1   -        virtualbox   Running   tcp://192.168.99.100:2376           v18.03.1-ce
myvm2   -        virtualbox   Running   tcp://192.168.99.101:2376           v18.03.1-ce

3、初始化swarm並且為其增加節點

您可以使用docker-machine ssh向VM發送命令。 使用docker swarm init指示m

yvm1成為一個swarm管理器:

$ docker-machine ssh myvm1 "docker swarm init --advertise-addr 192.168.99.100" Swarm initialized: current node (rxdphwlo6tpo60ql4k1mby8zx) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-63xho3dyvfjt76ivusisk6j1nsrwo9thto8frgja83jl7k04mp-eyopgohzj6agbox1o53swpj38 192.168.99.100:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

也可以使用以下命令進入myvm1虛擬機,然后再然后再執行swarm初始化操作

//進入虛擬機
$ docker-machine --native-ssh ssh myvm1

//初始化swarm
$ docker swarm init --advertise-addr 192.168.99.100

如您所見,對docker swarm init的輸出包含一個docker swarm join命令,您可以在要添加的任何節點上執行此命令,加入swarm作為一個worker節點。

復制此命令,並通過docker-machine ssh將其發送到myvm2,讓myvm2作為worker加入你的新swarm:

$ docker-machine ssh myvm2 "docker swarm join --token SWMTKN-1-63xho3dyvfjt76ivusisk6j1nsrwo9thto8frgja83jl7k04mp-eyopgohzj6agbox1o53swpj38 192.168.99.100:2377" This node joined a swarm as a worker.

恭喜你,你已經創建了你的第一個swarm!

在管理器上運行docker node ls以查看此swarm中的節點:

$ docker-machine ssh myvm1 "docker node ls" ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION rxdphwlo6tpo60ql4k1mby8zx * myvm1 Ready Active Leader 18.03.1-ce tbkcetrx4y6bpbl55hvjgqhaj myvm2 Ready Active 18.03.1-ce

4、離開一個swarm

如果你想重新開始,可以在每個節點運行docker swarm leave。

5、在swarm群集上部署您的應用程序

困難的部分結束了。 現在,您只需重復第2部分中使用的過程即可部署到新的swarm上。 請記住,只有像myvm1這樣的群體管理器才能執行Docker命令; worker只是為了提供能力。

與以前一樣,運行以下命令在myvm1上部署應用程序。

//復制文件到myvm1
$ docker-machine scp docker-compose.yml myvm1:/home/docker
//在myvm1執行命令,部署集群應用
$ docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab" 

現在您可以使用第2部分中使用的相同docker命令。只是這次注意到服務(和相關容器)已在myvm1和myvm2之間分配

$ docker service ps getstartedlab_web
ID                  NAME                  IMAGE                       NODE                DESIRED STATE       CURRENT STATE           ERROR               PORTS
m09niqvz3me5        getstartedlab_web.1   abs52121/friendlyhello:v1   myvm1               Running             Running 7 minutes ago
dqe31n93su10        getstartedlab_web.2   abs52121/friendlyhello:v1   myvm2               Running             Running 7 minutes ago
qe8ltg98230g        getstartedlab_web.3   abs52121/friendlyhello:v1   myvm1               Running             Running 7 minutes ago
u830cf28y0d2        getstartedlab_web.4   abs52121/friendlyhello:v1   myvm2               Running             Running 7 minutes ago
q8csws9zijtu        getstartedlab_web.5   abs52121/friendlyhello:v1   myvm2               Running             Running 7 minutes ago

6、訪問您的群集

您可以從myvm1或myvm2的IP地址訪問您的應用程序。

您創建的網絡在它們之間共享並進行負載平衡。 運行docker-machine ls獲取虛擬機的IP地址,並在瀏覽器上訪問其中任何一個,點擊刷新(或只是通過curl訪問)。

訪問時有5個容器ID隨機展示,這表明了負載平衡。兩個IP地址都能訪問的原因是swarm中的節點參與入口路由網格。 這可確保部署在swarm中某個端口的服務始終將該端口保留給自身,無論實際運行容器的是哪個節點。 下面是一個圖表,說明在三節點群上的端口8080上發布的名為my-web的服務的路由網格是什么樣子的:

routing mesh diagram

7、迭代和擴展您的應用程序

  • 在這里您可以使用上面提到的所有知識。
  • 通過更改docker-compose.yml文件來擴展應用程序。
  • 通過編輯代碼更改應用程序行為,然后重建並推送新鏡像。 (為此,請按照您之前用於構建應用程序並發布鏡像的相同步驟)。
  • 在任何一種情況下,只需再次運行docker stack deploy來部署這些更改。
  • 您可以使用myvm2上使用的相同docker swarm join命令將任何機器(物理或虛擬)加入此群,並將容量添加到群集中。 之后只需運行docker stack deploy,您的應用就可以利用新資源。

五、清理和退出

你可以用docker stack rm拆掉堆棧。 例如:

$ docker stack rm getstartedlab


原文地址:https://www.cnblogs.com/cblogs/p/docker-swarm.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM