動手學Docker-第三彈-Docker網絡

完整項目請查看Github:鏈接
或通過gitbook在線查看: 鏈接

Docker網絡

Docker單機網絡

關於網絡基礎知識大家請系統學習計算機網絡相關內容。

這裏介紹兩個幾個常用命令:

  • ping:查看指定IP是否可達 ping 192.168.0.1
  • telnet:查看服務是否可用 telnet 192.168.0.1 80,有的地址不可以ping但是可以用telnet。
  • curl:用來請求 Web 服務器。它的名字就是客戶端(client)的 URL 工具的意思。
  • wget:一個下載文件的工具。
  • ip a:顯示IP地址。

查看docker的網絡:

docker network ls

可以看到在docker中有三種網絡:

在這裏插入圖片描述

默認情況下容器使用的是橋接也就是Bridge Network,之後我們啓動一個容器並查看網絡具體內容

docker run -d --name test1 busybox /bin/sh -c "while true;do sleep 3600;done"
docker inspect 0b464e45177b(改成你查看到的NETWORK ID)

在network的具體細節內我們可以看到containers中包含了我們剛纔創建的容器

在這裏插入圖片描述

可以看到我們當前的容器是連接到了bridge的網絡中。在我們的主機和容器之間會創建一對vethnet以便於容器和主機之間相互通信,在主機的終端上我們可以直接ping通容器的ip地址。

這時我們再創建一個容器

docker run -d --name test2 busybox /bin/sh -c "while true;do sleep 3600;done"

再次查看network的具體內容

在這裏插入圖片描述

同時test2也會創建一堆vethnet,test1和test2的vethnet端口會都連接在一個bridge上,所以他們兩個之間可以相互ping通。

在這裏插入圖片描述

在已經知道了兩個容器之間可以相互訪問的情況下,我們現在需要實現這樣一個需求:

  • 首先啓動另一個容器db,在這個容器上運行數據庫服務
  • 同時啓動一個容器web,這個容器中我們可以運行一個用戶註冊服務
  • 用戶點擊註冊後,web容器將數據存儲到dbrongqi中

以上的這個操作必然要涉及兩個容器的網絡鏈接,我們知道可以通過IP地址相互ping通,但是在大規模集羣的情況下不可能手動的去指定IP,這個時候我們如何讓這兩個容器知道對方的存在呢?

我們可以在創建容器時使用--link參數,來制定我們創建的這個容器要連接到哪個容器上。

docker run -d --name test2 --link test1 busybox /bin/sh -c "while true;do sleep 3600;done"

之後我們進入test2中,ping test1的IP地址和test1都可以ping通。也就是我們在使用--link時是創建的DNS服務,將test1映射到172.17.0.2上。

在這裏插入圖片描述

我們也可以手動創建一個network,在創建容器時將容器連接到我們自己創建的network上,此時如果我們在自建的網絡上創建兩個容器,他們兩個之間是默認link好的。

Docker端口映射

我們啓動一個容器裏面一定會運行一些服務,但是這些服務我們如何才能讓外界訪問到呢?首先肯定是連接好網絡,這之前我們已經說過了。另一個重要的就是端口映射。

假如說我們在服務器上啓動nginx的服務,他默認是通過80端口來訪問的,但是我們如何通過訪問服務器的80端口來默認的訪問到容器中的nginx服務呢?我們在運行容器時可以使用這個命令:

docker run --name web -d -p 80:80 nginx

我們通過-p參數來將容器的80端口映射到服務器的80端口上,這樣我們訪問服務器的80端口時就會直接請求nginx服務。

我們容器的IP地址:

在這裏插入圖片描述

Linux服務器的IP地址分別是:

在這裏插入圖片描述

然後我們訪問Linux服務器的80端口:

在這裏插入圖片描述

可以看到確實是可以成功映射的。

flask-redis實戰

我們這個應用是使用flask搭建一個應用,這個應用是我們每訪問一次網址就會在redis的數據庫上加1。

首先我們創建一個啓動redis服務的容器

docker run -d --name redis redis

之後我們編寫一下python文件,名字叫做app.py

from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)


@app.route('/')
def hello():
    redis.incr('hits')
    return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)

在創建Dockerfile,並編輯裏面的內容

FROM python:2.7
COPY . /app
WORKDIR /app
RUN pip install flask redis
EXPOSE 5000
CMD [ "python", "app.py" ]

然後根據Dockerfile創建我們自己的鏡像

docker build -t su/flask-redis .

最後將我們自己創建的鏡像加載成容器對外提供服務,並且將容器的5000端口映射到服務器的5000端口

docker run -d --link redis -p 5000:5000 --name flask-redis -e REDIS_HOST=redis su/flask-redis

我們來看一下效果,首次訪問

在這裏插入圖片描述

再訪問一次看一下效果

在這裏插入圖片描述

可以看到我們已經實現了多容器應用的部署💯。

Docker多機網絡

剛纔我們已經成功的實現了flask-redis應用程序,但是還存在一個問題,我們的服務可能是訪問量很大的一個服務,這時需要我們將redis和flask部署到不同的服務器上,我們怎麼才能讓這兩個部署在不同服務器上的容器相互通信呢?

在這裏插入圖片描述

兩個容器之間數據的傳遞使用的技術是VXLAN,他是一個overlay網絡的實現,更多內容可以參考:關於VLAN和VXLAN的理解

想要實現兩個容器進行通信我們需要一個技術來支持就是etcd,關於etcd的更多內容大家可以查看:Etcd 使用入門高可用分佈式存儲 etcd 的實現原理。etcd 的官方將它定位成一個可信賴的分佈式鍵值存儲服務,它能夠爲整個分佈式集羣存儲一些關鍵數據,協助分佈式集羣的正常運轉。也就是我們的兩臺服務器要分別在etcd服務上進行註冊,以便於互相識別。

flask-redis多機實戰

接下來我們將之前的那個flask-redis實戰轉換爲多機的實戰

首先準備兩臺服務器,我這裏準備了兩臺服務器分別是node1和node2,他們的ip地址分別是:192.168.205.10192.168.205.11

接下來在node1節點上運行命令

vagrant@node1:~$ wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
vagrant@node1:~$ tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
vagrant@node1:~$ cd etcd-v3.0.12-linux-amd64
vagrant@node1:~$ nohup ./etcd --name docker-node1 --initial-advertise-peer-urls http://192.168.205.10:2380 \
--listen-peer-urls http://192.168.205.10:2380 \
--listen-client-urls http://192.168.205.10:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.205.10:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:2380 \
--initial-cluster-state new&

之後在node2上運行命令

vagrant@node2:~$ wget https://github.com/coreos/etcd/releases/download/v3.0.12/etcd-v3.0.12-linux-amd64.tar.gz
vagrant@node2:~$ tar zxvf etcd-v3.0.12-linux-amd64.tar.gz
vagrant@node2:~$ cd etcd-v3.0.12-linux-amd64/
vagrant@node2:~$ nohup ./etcd --name docker-node2 --initial-advertise-peer-urls http://192.168.205.11:2380 \
--listen-peer-urls http://192.168.205.11:2380 \
--listen-client-urls http://192.168.205.11:2379,http://127.0.0.1:2379 \
--advertise-client-urls http://192.168.205.11:2379 \
--initial-cluster-token etcd-cluster \
--initial-cluster docker-node1=http://192.168.205.10:2380,docker-node2=http://192.168.205.11:23

檢查一下etcd的狀態:

vagrant@node2:~/etcd-v3.0.12-linux-amd64$ ./etcdctl cluster-health

接下來我們要重啓docker服務

在node1上運行命令

sudo service docker stop
sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.205.10:2379 --cluster-advertise=192.168.205.10:2375&

在node2上運行命令

sudo service docker stop
sudo /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --cluster-store=etcd://192.168.205.11:2379 --cluster-advertise=192.168.205.11:2375&

接下來我們在node1上創建一個名爲demo的overlay網絡

docker network create -d overlay demo

我們現在在node1和node2上查看一下網絡情況

在這裏插入圖片描述
在這裏插入圖片描述

我們雖然沒有在node2上創建demo網絡,但是通過etcd會同步的進行創建,這樣我們兩臺服務器上都有了一個叫做demo的網絡,接下來我們創建容器時就可以將demo作爲容器的網絡。

首先在node2上創建redis容器

docker run -d --name redis --net demo redis

接下來在node1上創建flask容器

docker run -d --net demo -p 5000:5000 --name flask-redis -e REDIS_HOST=redis su/flask-redis

接下來我們看一下實驗結果

在這裏插入圖片描述
在這裏插入圖片描述
可以看到我們已經實現了多容器應用的多機部署💯。


歡迎大家關注我們的公衆號:知識沉澱部落。
知識沉澱部落

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章