《docker入門與實踐》筆記
Docker的網(wǎng)絡(luò)其實是利用Linux上的網(wǎng)絡(luò)命名空間和虛擬網(wǎng)絡(luò)設(shè)備(veth pair)實現(xiàn)的。
一、基本原理
- 直觀上看疾宏,要實現(xiàn)網(wǎng)絡(luò)通信,機器需要至少一個網(wǎng)絡(luò)接口(物理網(wǎng)絡(luò)接口或虛擬網(wǎng)絡(luò)接口)與外界相通触创,并可以收發(fā)數(shù)據(jù)包坎藐;此外,如果要實現(xiàn)不同子網(wǎng)之間的通信哼绑,需額外配置路由岩馍。
- Docker 中的網(wǎng)絡(luò)接口默認都是虛擬的接口。虛擬接口的優(yōu)勢就是轉(zhuǎn)發(fā)效率極高抖韩。這是因為Linux通過內(nèi)核中進行數(shù)據(jù)復(fù)制來實現(xiàn)虛擬接口之間的數(shù)據(jù)轉(zhuǎn)發(fā)蛀恩,即發(fā)送接口的發(fā)送緩存中的數(shù)據(jù)包將被直接復(fù)制到接收皆苦的接受緩存中,無需通過外部物理網(wǎng)絡(luò)設(shè)備進行交換茂浮。這個拷貝實在內(nèi)核態(tài)直接完成双谆,不需要兩態(tài)切換。
- Docker容器網(wǎng)絡(luò)很好的利用了Linux的虛擬網(wǎng)絡(luò)技術(shù)席揽,它在本地主機和容器內(nèi)分別創(chuàng)建一個虛擬接口顽馋,并讓它們彼此連同。
二幌羞、網(wǎng)絡(luò)創(chuàng)建過程
- 創(chuàng)建一對虛擬接口寸谜,分別放到本地主機和新容器的命名空間中。
// 創(chuàng)建一個容器
docker run -it --rm busybox
- 本地主機一端的虛擬接口連接到默認的docker0網(wǎng)橋或指定的網(wǎng)橋上属桦,并具有一個以veth開頭的唯一名字熊痴,如:veth22f630c
// 查看主機分配的veth接口
ifconfig 或者ip addr show
// 查看veth22f630c接口連接到docker0網(wǎng)橋上
brctl show
- 容器一端的虛擬接口將放到新創(chuàng)建的容器中,并修改名字為eth0地啰。這個接口只有容器的命名空間可見愁拭。
- 從網(wǎng)橋可用地址段中獲取一個空閑的地址分配給容器的eth0(例如: 172.17.0.2/16),并配置默認網(wǎng)關(guān)為docker0網(wǎng)卡的內(nèi)部接口docker0的IP地址(例如:172.17.0.1/16)
// 查看docker0的IP
ifconfig docker0
// 查看容器的IP亏吝,網(wǎng)關(guān)
docker inspect fc8da94bafdd(containerid)
- 完成這些之后岭埠,容器就可以使用eth0虛擬網(wǎng)卡來連接其他容器和訪問外部網(wǎng)絡(luò)了。
三蔚鸥、網(wǎng)絡(luò)配置
docker運行的時候通過--net參數(shù)指定容器的網(wǎng)絡(luò)配置惜论,有4個可選值bridge、host止喷、container馆类、none:
- --net=bridge:默認值,在Docker網(wǎng)橋上為容器創(chuàng)建新的網(wǎng)絡(luò)棧。
- --net=host:告訴 Docker不要將容器網(wǎng)絡(luò)放到隔離的命名空間中弹谁,即不要容器化容器內(nèi)的網(wǎng)絡(luò)乾巧。此時容器使用本地主機的網(wǎng)絡(luò),它擁有完全的本地主機接口訪問權(quán)限句喜。容器進程可以跟主機其他root進程一樣打開低范圍的端口,可以訪問本地網(wǎng)絡(luò)服務(wù)比如D-bus,還可以讓容器做一些影響整個主機系統(tǒng)的事情,比如重啟主機沟于。因此使用這個選項的時候要非常小心咳胃。如果進一步的使用-- privileged=true參數(shù),
容器甚至?xí)辉试S直接配置主機的網(wǎng)絡(luò)堆棧旷太。 - --net=container:讓Docker將新建容器的進程放到一個已存在容器的網(wǎng)絡(luò)棧中展懈,新容器進程有自己的文件系統(tǒng)、進程列表和資源限制供璧,但會和已存在的容器共享IP地址和端口等網(wǎng)絡(luò)資源存崖,兩者進程可以直接通過lo環(huán)回接口通信。
- --net=none:讓Docker將新容器放到隔離的網(wǎng)絡(luò)棧中睡毒,但是不進行網(wǎng)絡(luò)配置来惧。之后,用戶可以自己進行配置演顾。
四违寞、網(wǎng)絡(luò)配置細節(jié)
用戶使用--net=none后,Docker將不對容器網(wǎng)絡(luò)進行配置偶房。下面趁曼,將手動完成配置網(wǎng)絡(luò)的整個過程。
- --net=none創(chuàng)建一個容器:
// 創(chuàng)建容器(containerid:fc1f71546394)
docker run -it --rm --net=none busybox
- 在本地主機查找容器的進程id棕洋,并為它創(chuàng)建網(wǎng)絡(luò)命名空間:
// 查看容器的進程id
docker inspect -f "{{.State.Pid}}" fc1f71546394
// 為容器創(chuàng)建網(wǎng)絡(luò)命名空間
pid=58930
mkdir -p /var/run/netns
ln -s /proc/$pid/ns/net /var/run/netns/$pid
- 查看橋接網(wǎng)卡的IP和子網(wǎng)掩碼信息:
```
ip addr show docker0
```
- 創(chuàng)建一對"veth pair"接口veth_host和veth_container挡闰,綁定veth_host到網(wǎng)橋docker0,并啟動veth_host:
// 創(chuàng)建一對veth pair
sudo ip link add veth_host type veth peer name veth_container
// 將veth_host接口添加到docker0網(wǎng)橋上
sudo brctl addif docker0 veth_host
// 激活veth_host接口
sudo ip link set veth_host up
// 查看veth_host接口信息
ifconfig veth_host
// 查看docker0情況
brctl show
- 將veth_container接口放到容器的網(wǎng)絡(luò)命名空間掰盘,命名為eth0摄悯,啟動它并配置一個可用IP(172.17.0.3/16)和默認網(wǎng)關(guān)(172.17.0.1):
// 將veth_container接口放到容器的網(wǎng)絡(luò)命名空間
sudo ip link set veth_container netns $pid
// veth_container 設(shè)置容器內(nèi)的別名eth0
sudo ip netns exec $pid ip link set dev veth_container name eth0
// 激活容器內(nèi)的eth0接口
sudo ip netns exec $pid ip link set eth0 up
// 給容器內(nèi)的eth0設(shè)置ip
sudo ip netns exec $pid ip addr add 172.17.0.3/16 dev eth0
// 給容器內(nèi)的設(shè)置默認網(wǎng)關(guān)
sudo ip netns exec $pid ip route add default via 172.17.0.1
- 以上就是Docker配置網(wǎng)絡(luò)的具體過程
當容器終止后,Docker會清空容器愧捕,容器內(nèi)的網(wǎng)絡(luò)接口會隨著網(wǎng)絡(luò)命名空間一起被清除奢驯,veth_host 接口也會自動從docker0卸載并清除。