docker高級網絡配置
#說明: 當docker啟動時,會自動在宿主機上創建一個docker0虛擬網橋,實際上是linux的一個bridge,可理解為一個軟件交換機,它會在掛載到它的網口之間進行轉發
#ip address |grep docker
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
17: veth4967b39@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
19: veth183c4ca@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
21: vethc0abe5c@if20: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
同時docker隨機分配一個本地未占用的私有網絡中的一個地址給docker0接口,如上圖中的172.17.0.1,掩碼16位,之后啟動的容器內的網口也會自動分配一個網段的地址
當創建一個容器時,同時會創建一個veth pair接口(當數據發送到一個接口時,另一個接口也會接收相同的數據包),這對接口一個在容器內 即eth0,另一端在本地並被掛載到docker0網橋,名稱以veth開頭,通過這種方式,主機可以跟容器通信,容器之間也可以通信. docker就創建了在主機和所有容器之間的一個虛擬共享網絡。
1、快速配置
只有在docker服務啟動的時候才能配置,而且不能馬上生效的有:
-b BRIDGE or --bridge=BRIDGE --指定容器掛載的網橋
--bip=CIDR --定制docker0的掩碼
-H SOCKET... or --host=SOCKET... --Docker服務端接收命令的通道
--icc=true|false --是否支持容器之間進行通信
--ip-forward=true|false --請看下文容器之間的通信
--iptables=true|false --是否允許Docker添加iptables規則
--mtu=BYTES --容器網絡中的MTU
既可在啟動服務時指定,也可在容器啟動時指定,當在docker服務啟動時指定會成為默認值,后面執行容器啟動時可覆蓋設置的默認值。
--dns=IP_ADDRESS... #指定特定的DNS服務器
--dns-search=DOMAIN... #指定dns搜索域
只在容器啟動時使用,針對容器的特性內容:
-h HOSTNAME or --hostname=HOSTNAME #配置容器主機名
--link=CONTAINER_NAME:ALIAS #添加到另一個容器的連接
--net=bridge|none|container:NAME_or_ID|host #配置容器的橋接模式
-p SPEC or --publish=SPEC #映射容器端口到宿主主機
-P or --publish-all=true|false #映射容器所有端口到宿主主機
2、配置DNS
在容器中使用mount命令可以看到掛載信息里有三個相關的配置文件,這樣可以讓宿主機的dns信息發生變更后,容器的dns可以立刻得到更新
/dev/mapper/centos-root on /etc/resolv.conf type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/centos-root on /etc/hostname type xfs (rw,relatime,attr2,inode64,noquota)
/dev/mapper/centos-root on /etc/hosts type xfs (rw,relatime,attr2,inode64,noquota)
如想手動指定容器的配置,進入容器后可使用下面的選項
root@29e314e74d71:/# cat /etc/hostname
29e314e74d71
root@29e314e74d71:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 29e314e74d71
--link=CONTAINER_NAME_NAME:ALIAS
#創建容器時使用上面的選項,可添加一個其它的容器主機名至/etc/hosts文件中,讓新創建的容器可使用ALIAS就可連接另一個容器
--dns=IP_ADDRESS
#創建容器時添加dns服務器到容器/etc/resolv.conf中.
--dns-search=DOMAIN
#創建容器時設定容器的 搜索域
***當創建容器時沒有指定上面選項時,docker會默認用宿主機上的配置來給容器
3、容器訪問控制
#容器想訪問外部網絡,需本地系統轉發開啟支持
sysctl net.ipv4.ip_forward #為1支持,為0為沒開啟轉發
sysctl -w net.ipv4.ip_forward=1
docker run --rm --name mycentos1 -it centos /bin/bash
ping baidu.com #測試能否訪問外部網絡
#永久開啟為以下
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p
容器之間訪問
#需兩個條件支持
a、容器之間的網絡已經互聯,默認所有的容器會連接到docker0網橋上
b、本地系統的iptables是否允許
默認情況,容器之間是互通的
訪問所有的端口
容器服務啟動時,iptables會自動添加一個轉發策略,策略是通過還是禁止取決於配置--icc=true/false,如手動指定--iptables=false,則不會添加iptables規則
默認不同容器之間是網絡互通的,如為安全考慮要禁止,可更改/etc/default/docker配置DOCKER_OPTS=--icc=false
容器訪問外部網絡
容器所有到外部網絡的連接,源地址都會nat到本地宿主機系統的ip地址,iptables nat規則有源地址偽裝操作
# iptables -t nat -nL
target prot opt source destination
MASQUERADE all -- 172.17.0.0/16 0.0.0.0/0
外部網絡訪問容器
當容器啟動時-p或-P,會在iptables nat表中添加相應的規則轉行相應端口的轉發
iptables -t nat -nL
Chain DOCKER (2 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:32768 to:172.17.0.2:80
DNAT tcp -- 0.0.0.0/0 127.0.0.1 tcp dpt:8080 to:172.17.0.3:80
DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8081 to:172.17.0.4:80
4、配置docker0網橋
docker服務默認會創建一個docker0網橋,它在內核層連通了其它物理網卡和虛擬網卡,這就將所有容器和本地主機都放到同一個物理網絡當中。
docker0接口的ip和子網會默認指定一個,並且定義了MTU,這些值都可以在服務器啟動時進行配置
--bip=CIDR #--ip地址加掩碼格式,如 172.17.0.1/16
--mtu=BYTES #覆蓋默認的mtu配置
yum -y install bridge-utils #安裝包才有brctl
brctl show #查看網橋和端口信息
每次創建新容器時,docker會從可用的地址段中分一個給容器的eth0端口,使用本地主機上docker0接口作為所有容器的默認網關
docker run -it --rm --name mycent1 centos /bin/bash
ip add
#inet 172.17.0.5/16 brd 172.17.255.255 scope global eth0
ip route
#default via 172.17.0.1 dev eth0
5、自定義網橋
除了默認docker0網橋,也可以啟動服務時使用 -b BRIDGE或--bridge=BRIDGE來指定使用網橋來連接各個容器
5.1、創建網橋
systemctl stop docker #停止docker服務
ip link set dev docker0 down #停止docker0網橋
brctl delbr docker0 #刪除docker0網橋
brctl addbr br0 #新建bridge0網橋
ip addr add 192.168.3.1/24 dev br0 #綁定ip給br0網橋
ip link set dev br0 up #啟動br0網橋
brctl show 查看網橋信息
yum -y install net-tools #安裝ifconfig命令
ifconfig br0 #查看br0網橋信息
5.2、配置docker服務
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H unix:// $DOCKER_OPTS #在ExecStart末尾添加 $DOCKER_OPTS
EnvironmentFile=-/etc/default/docker #指定配置文件的路徑
vim /etc/default/docker
DOCKER_OPTS="-b=br0"
systemctl start docker #啟動docker服務
docker run --rm -ti --name mycent2 centos /bin/bash #創建一個容器
ifconfig #查看容器ip,檢查是否橋接在br0上
ping qq.com #測試網絡及到網橋是否通
---------如果容器沒有ifconfig和ping命令--------------
在容器中執行以下命令,獲取命令相關的包安裝
apt-get update
apt install net-tools
apt install iputils-ping
-----------------------------------------------------
6、創建一個點到點的連接
默認所有容器會連接到docker0的虛擬子網中
如需兩個容器之間可以不通過宿主機網橋進行連接,創建一對peer接口,放入兩個容器中,配置成點對點鏈路類型
6.1、兩個終端啟動兩個容器
docker run -it --rm --name mytest1 --net=none centos /bin/bash
docker run -it --rm --name mytest2 --net=none centos /bin/bash
6.2、(在第三個終端操作)找到進程號,創建網絡命名空間的跟蹤文件
docker inspect -f '{{.State.Pid}}' mytest1
18192
docker inspect -f '{{.State.Pid}}' mytest2
18311
mkdir -p /var/run/netns
ln -s /proc/18192/ns/net /var/run/netns/18192
ln -s /proc/18311/ns/net /var/run/netns/18311
6.3、創建一對peer接口,然后配置路由---同樣在第三個終端操作
ip link add A type veth peer name B
ip link set A netns 18192
ip netns exec 18192 ip addr add 10.1.1.1/32 dev A
ip netns exec 18192 ip link set A up
ip netns exec 18192 ip route add 10.1.1.2/32 dev A
ip link set B netns 18311
ip netns exec 18311 ip addr add 10.1.1.2/32 dev B
ip netns exec 18311 ip link set B up
ip netns exec 18311 ip route add 10.1.1.1/32 dev B
6.4、測試兩容器通信
mytest1上測試
#ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.098 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.076 ms
mytest2上測試
ping 10.1.1.1
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.084 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=0.058 ms