[docker] 淺談Docker:網(wǎng)絡(luò)模式及從容器內(nèi)部訪問宿主機(jī)的IP地址
0 序
- 本文系轉(zhuǎn)載參考文獻(xiàn),屬于非原創(chuàng)的筆記類博文。
- 最新結(jié)論:從Docker容器內(nèi)部訪問宿主的IP地址的幾種方法,推薦 基于 Bridge 模式 +
--link訪問別的服務(wù) +172.16.0.1(訪問宿主機(jī))。
1 Docker的網(wǎng)絡(luò)模式
- docker是比較流行的容器技術(shù),docker鏡像方便程序員對應(yīng)用統(tǒng)一的要求,打包部署便捷。但是不足的地方在于docker的網(wǎng)絡(luò)方面。
- docker有4種網(wǎng)絡(luò)模式,分別是:
- host模式
- container模式
- none模式
- bridge模式
-
分別使用
-net, --network指定。如:-net=host、-net=container(容器名或ID)、-net=bridge指定各種網(wǎng)絡(luò)模式。 -
Docker 默認(rèn)網(wǎng)絡(luò)
Docker安裝后,默認(rèn)會(huì)創(chuàng)建下面三種網(wǎng)絡(luò)類型:
[root@172 /]# docker network ls
NETWORK ID NAME DRIVER SCOPE
7bae40b7ba3b bridge bridge local
a76157f2257d host host local
c8e7302eb8c8 none null local
啟動(dòng) Docker 的時(shí)候,用
--network參數(shù),可以指定網(wǎng)絡(luò)類型,如:
[root@172 /]# docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:latest /bin/bash
1.1 Host模式
簡介
- 在
host模式下,容器與宿主機(jī)共享Network Namespace。
- 容器不會(huì)獲得獨(dú)立的網(wǎng)絡(luò)命名空間,而是使用宿主機(jī)的IP地址和端口。
這樣,容器可以直接使用宿主機(jī)的網(wǎng)絡(luò)接口與外界通信,網(wǎng)絡(luò)性能較好,但容器之間的網(wǎng)絡(luò)隔離性較差。
簡言之:與宿主機(jī)在同一網(wǎng)絡(luò)中,但是沒有獨(dú)立的IP地址。
- docker使用Linux的Namespace隔離網(wǎng)絡(luò)等設(shè)施。
- 一個(gè)Network Namespace 提供了一份獨(dú)立的網(wǎng)絡(luò)環(huán)境,包括網(wǎng)卡、路由、Iptable規(guī)則等都與其他的Network Namespace隔離。
- 當(dāng)我們啟動(dòng)容器指定其網(wǎng)絡(luò)模式為host時(shí),啟動(dòng)指定命令如下:
docker run --name xxx --net=host xxxx
docker run -itd --name test1 --network host centos:7 /bin/bash
此處使用
-net指定docker容器所使用的網(wǎng)絡(luò)模式。
- 在使用host模式時(shí),容器將不會(huì)獲得一個(gè)獨(dú)立的Network Namespace,不會(huì)模擬出自己的網(wǎng)卡、配置自己的ip等。而是和宿主機(jī)共用一個(gè)namespace。所有此模式使用的網(wǎng)絡(luò)和宿主機(jī)上的網(wǎng)絡(luò)是相同的。
使用
- 在運(yùn)行容器時(shí),可以使用
--network=host選項(xiàng),這將使得容器共享【宿主機(jī)】的網(wǎng)絡(luò)命名空間,使得容器內(nèi)部可以直接訪問宿主的IP地址。
Docker 提供了一個(gè)主機(jī)網(wǎng)絡(luò),讓容器可以共享主機(jī)的網(wǎng)絡(luò)堆棧。這種方法意味著容器內(nèi)的本地主機(jī)解析為物理主機(jī),而不是容器本身。通過添加 --network=host 標(biāo)志與主機(jī)網(wǎng)絡(luò)一起啟動(dòng)容器:
docker run --network=host your_image_name
例如:
docker run -d --network=host my-container:latest
build docker鏡像時(shí),使用宿主機(jī)網(wǎng)絡(luò)
參考文獻(xiàn): docker build - network 解決 docker build timeout - geekdaxue.co
- 使用 Dockerfile 來 docker build 鏡像時(shí),默認(rèn)使用的 bridge 網(wǎng)絡(luò)環(huán)境;而 RUN 等命令經(jīng)常需要聯(lián)網(wǎng)下載依賴,由于公司加密軟件的限制,造成RUN命令使用bridge時(shí)無法聯(lián)網(wǎng)
- 想到使用 host 網(wǎng)絡(luò)應(yīng)該可以上網(wǎng),host網(wǎng)絡(luò)中,docker 容器沒有自己的網(wǎng)卡和ip,不使用birdge網(wǎng)絡(luò),直接使用本機(jī)的網(wǎng)絡(luò);只要本機(jī)可以上網(wǎng),docker build時(shí)的RUN命令就可以使用網(wǎng)絡(luò)
docker build --network host .
--network標(biāo)志指定在構(gòu)建過程中,RUN命令使用哪種網(wǎng)絡(luò)模式。
1.2 container模式
- container模式是將新創(chuàng)建的容器和已經(jīng)存在的容器共享一個(gè)Network Namespace ,而不是和宿主機(jī)共享。
- 在創(chuàng)建容器時(shí)指定容器,就會(huì)共享被指定的容器的ip、端口等。兩個(gè)容器僅僅是網(wǎng)絡(luò)共享,其他當(dāng)面還是隔離的,如文件系統(tǒng)、進(jìn)程列表等等。倆個(gè)容器之間通過IO網(wǎng)卡進(jìn)行本地通信。
1.3 none模式
- 此模式下,docker擁有自己的網(wǎng)絡(luò)命名空間,但是不會(huì)為容器進(jìn)行任何的網(wǎng)絡(luò)配置,容器沒有網(wǎng)卡、ip、路由等信息,需要我們自己為docker容器添加網(wǎng)卡配置ip,不會(huì)創(chuàng)建網(wǎng)絡(luò)設(shè)備。
1.4 bridge模式【默認(rèn)模式】
簡介
-
bridge模式是docker默認(rèn)的網(wǎng)絡(luò)模式,此模式創(chuàng)建一對虛擬網(wǎng)絡(luò)設(shè)備,一半在容器上,一半再虛擬網(wǎng)絡(luò)橋上。為每一個(gè)容器分配NetWork Namespace、網(wǎng)卡、ip等信息,將docker容器連接到虛擬網(wǎng)橋上。 -
此模式比較常用,在我們的docker服務(wù)啟動(dòng)時(shí),主機(jī)上會(huì)創(chuàng)建一個(gè)名為docker0的虛擬網(wǎng)橋,在主機(jī)上啟動(dòng)的容器服務(wù)都會(huì)連接到這個(gè)虛擬網(wǎng)橋上,和交換機(jī)的原理有些類似,此時(shí)主機(jī)上的容器通過此"交換機(jī)"連接在二層網(wǎng)絡(luò)中。
-
再后就是為容器分配ip,Docker會(huì)從RFC1918(私有網(wǎng)絡(luò)地址分配)所定義的私有ip網(wǎng)段中選擇一個(gè)核宿主機(jī)不同的ip地址和子網(wǎng)分配給docker0,連接到docker0的容器就從此子網(wǎng)中選擇一個(gè)未占用的ip使用。
一般會(huì)使用
172.17.0.0/16這個(gè)網(wǎng)段,并將172.17.0.0/16分配給docker0網(wǎng)橋。
在宿主機(jī)上使用ifconfig可以看到docker0,可以看做是網(wǎng)橋的管理接口,在宿主機(jī)上作為一塊虛擬網(wǎng)卡使用。在其他大佬的文章上找到一張圖,很清晰的畫出了網(wǎng)絡(luò)拓?fù)洹K拗鳈C(jī)的ip地址為eth0

- 常用的還是
bridge模式,容器之間可以通信,創(chuàng)建容器時(shí)默認(rèn)創(chuàng)建網(wǎng)絡(luò)模式。
使用
- 使用特殊的宿主地址
在Linux系統(tǒng)中,可以使用特殊的IP地址
172.17.0.1來代表【宿主機(jī)】,這個(gè)IP地址通常用于Docker默認(rèn)的網(wǎng)絡(luò)橋接模式中。

- 案例1:下面畫一張拓?fù)鋱D來詳細(xì)地講述docker內(nèi)的容器是如何進(jìn)行通信的。

如上圖所示,在宿主機(jī)中,在運(yùn)行容器時(shí)默認(rèn)采取【bridge網(wǎng)絡(luò)模式】,當(dāng)docker服務(wù)啟動(dòng)時(shí)會(huì)創(chuàng)建docker0網(wǎng)卡,所有的容器借助于此虛擬網(wǎng)卡和宿主機(jī)以及外界進(jìn)行通信,容器之間可以直接通信。
上述方式需要進(jìn)入容器中查看
/etc/hosts文件中的主機(jī)的信息,顯得過于麻煩,在運(yùn)行docker容器時(shí)可以直接將容器的ip對應(yīng)于域名,容器之間互相訪問通信時(shí)直接根據(jù)域名通信即可。
- 使用
docker --link模式來實(shí)現(xiàn),實(shí)現(xiàn)方式 如下,使用docker跑起亂來一個(gè)nginx容器
再跑起來一個(gè)基于centos的容器,在此時(shí)使用–link命令在此容器中直接添加nginx容器的域名解析信息(將mynginx的172.17.0.2解析為nginx1,之后在centos創(chuàng)建的容器中可以直接訪問nginx1即可訪問mynginx容器),操作如下。
docker run --name mycentos -id --link mynginx:nginx1 centos
創(chuàng)建完成之后進(jìn)入mycentos容器中,使用curl nginx1就可直接訪問mynginx容器中的服務(wù)了,方便快捷。
2 補(bǔ)充:【掛載宿主的網(wǎng)絡(luò)命名空間到容器內(nèi)部】
- 可以手動(dòng)掛載宿主的網(wǎng)絡(luò)命名空間到容器內(nèi)部。這種方法比較復(fù)雜,但是也是可行的。可以使用nsenter命令來實(shí)現(xiàn)這一點(diǎn)。
- 首先,需要獲取宿主的網(wǎng)絡(luò)命名空間ID:
sudo docker inspect --format '{{ .State.Pid }}' <container_id_or_name>
- 然后,使用
nsenter命令將容器加入到宿主的網(wǎng)絡(luò)命名空間中:
sudo nsenter --target <host_pid> --net <your_command>
這樣,就可以在容器內(nèi)部直接訪問宿主的網(wǎng)絡(luò)。
X 參考文獻(xiàn)
本文鏈接: http://www.rzrgm.cn/johnnyzen
關(guān)于博文:評論和私信會(huì)在第一時(shí)間回復(fù),或直接私信我。
版權(quán)聲明:本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協(xié)議。轉(zhuǎn)載請注明出處!
日常交流:大數(shù)據(jù)與軟件開發(fā)-QQ交流群: 774386015 【入群二維碼】參見左下角。您的支持、鼓勵(lì)是博主技術(shù)寫作的重要?jiǎng)恿Γ?

浙公網(wǎng)安備 33010602011771號