[docker] 淺談Docker:網絡模式及從容器內部訪問宿主機的IP地址

0 序

  • 本文系轉載參考文獻,屬於非原創的筆記類博文。
  • 最新結論:從Docker容器內部訪問宿主的IP地址的幾種方法,推薦 基於 Bridge 模式 + --link 訪問別的服務 + 172.16.0.1(訪問宿主機)。

1 Docker的網絡模式

  • docker是比較流行的容器技術,docker鏡像方便程序員對應用統一的要求,打包部署便捷。但是不足的地方在於docker的網絡方面。
  • docker有4種網絡模式,分別是:
  • host模式
  • container模式
  • none模式
  • bridge模式
  • 分別使用-net, --network指定。如:-net=host-net=container(容器名或ID)-net=bridge指定各種網絡模式。

1.1 Host模式

簡介

  • host模式相當於Vmware中的橋接模式,與宿主機在同一個網絡中,但是沒有獨立的IP地址
  • docker使用Linux的Namespace隔離網絡等設施。
  • 一個Network Namespace 提供了一份獨立的網絡環境,包括網卡路由Iptable規則等都與其他的Network Namespace隔離。
  • 當我們啓動容器指定其網絡模式爲host時,啓動指定命令如下:
docker run --name xxx --net=host xxxx

此處使用-net指定docker容器所使用的網絡模式。

  • 在使用host模式時,容器將不會獲得一個獨立的Network Namespace,不會模擬出自己的網卡、配置自己的ip等。而是和宿主機共用一個namespace。所有此模式使用的網絡和宿主機上的網絡是相同的。

使用

  • 在運行容器時,可以使用--network=host選項,這將使得容器共享【宿主機】的網絡命名空間,使得容器內部可以直接訪問宿主的IP地址。

Docker 提供了一個主機網絡,讓容器可以共享主機的網絡堆棧。這種方法意味着容器內的本地主機解析爲物理主機,而不是容器本身。通過添加 --network=host 標誌與主機網絡一起啓動容器:

docker run --network=host your_image_name

例如:

docker run -d --network=host my-container:latest

1.2 container模式

  • container模式是將新創建的容器和已經存在的容器共享一個Network Namespace ,而不是和宿主機共享。
  • 在創建容器時指定容器,就會共享被指定的容器的ip、端口等。兩個容器僅僅是網絡共享,其他當面還是隔離的,如文件系統、進程列表等等。倆個容器之間通過IO網卡進行本地通信。

1.3 none模式

  • 此模式下,docker擁有自己的網絡命名空間,但是不會爲容器進行任何的網絡配置,容器沒有網卡、ip、路由等信息,需要我們自己爲docker容器添加網卡配置ip,不會創建網絡設備。

1.4 bridge模式【默認模式】

簡介

  • bridge模式是docker默認的網絡模式,此模式創建一對虛擬網絡設備,一半在容器上,一半再虛擬網絡橋上。爲每一個容器分配NetWork Namespace、網卡、ip等信息,將docker容器連接到虛擬網橋上。

  • 此模式比較常用,在我們的docker服務啓動時,主機上會創建一個名爲docker0的虛擬網橋,在主機上啓動的容器服務都會連接到這個虛擬網橋上,和交換機的原理有些類似,此時主機上的容器通過此"交換機"連接在二層網絡中。

  • 再後就是爲容器分配ip,Docker會從RFC1918(私有網絡地址分配)所定義的私有ip網段中選擇一個核宿主機不同的ip地址和子網分配給docker0,連接到docker0的容器就從此子網中選擇一個未佔用的ip使用。

一般會使用172.17.0.0/16這個網段,並將172.17.0.0/16分配給docker0網橋
在宿主機上使用ifconfig可以看到docker0,可以看做是網橋的管理接口,在宿主機上作爲一塊虛擬網卡使用。在其他大佬的文章上找到一張圖,很清晰的畫出了網絡拓撲。宿主機的ip地址爲eth0

  • 常用的還是bridge模式,容器之間可以通信,創建容器時默認創建網絡模式。

使用

  • 使用特殊的宿主地址

在Linux系統中,可以使用特殊的IP地址172.17.0.1來代表【宿主機】,這個IP地址通常用於Docker默認的網絡橋接模式中。

  • 案例1:下面畫一張拓撲圖來詳細地講述docker內的容器是如何進行通信的。

如上圖所示,在宿主機中,在運行容器時默認採取【bridge網絡模式】,當docker服務啓動時會創建docker0網卡,所有的容器藉助於此虛擬網卡和宿主機以及外界進行通信,容器之間可以直接通信。

上述方式需要進入容器中查看/etc/hosts文件中的主機的信息,顯得過於麻煩,在運行docker容器時可以直接將容器的ip對應於域名,容器之間互相訪問通信時直接根據域名通信即可。

  • 使用docker --link模式來實現,實現方式 如下,使用docker跑起亂來一個nginx容器

再跑起來一個基於centos的容器,在此時使用–link命令在此容器中直接添加nginx容器的域名解析信息(將mynginx的172.17.0.2解析爲nginx1,之後在centos創建的容器中可以直接訪問nginx1即可訪問mynginx容器),操作如下。

docker run --name mycentos -id --link mynginx:nginx1 centos

創建完成之後進入mycentos容器中,使用curl nginx1就可直接訪問mynginx容器中的服務了,方便快捷。

2 補充方法:【掛載宿主的網絡命名空間到容器內部】

  • 可以手動掛載宿主的網絡命名空間到容器內部。這種方法比較複雜,但是也是可行的。可以使用nsenter命令來實現這一點。
  • 首先,需要獲取宿主的網絡命名空間ID:
sudo docker inspect --format '{{ .State.Pid }}' <container_id_or_name> 
  • 然後,使用nsenter命令將容器加入到宿主的網絡命名空間中:
sudo nsenter --target <host_pid> --net <your_command> 

這樣,就可以在容器內部直接訪問宿主的網絡。

X 參考文獻

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