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>
這樣,就可以在容器內部直接訪問宿主的網絡。