Docker Networking
本文基于马哥的docker和k8s视频总结, 在此致谢马哥.
Net名称空间主要用于: 隔离协议栈
docker network ls
NETWORK ID NAME DRIVER SCOPE
b0c512d53352 bridge bridge local # bridge <=> docker0
9a33978f0f9c host host local # 使用宿主机的网络
44dbf221814d none null local # 不使用网络
ip addr show docker0 # docker0是一个二层交换机, 也可以扮演二层的网卡
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:89:71:6b:33 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
docker container run --name b1 -it busybox
docker container run --name b2 -it busybox
# 同时开启两个container, 然后用工具查看会发现模拟出了两对网卡
yum -y install bridge-utils
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.024289716b33 no veth33f3a68
veth7a11ca8
virbr0 8000.5254004fa410 yes virbr0-nic
# 两对网卡都是一半插在作为bridge的docker0上, 另外一半插在container上
ip link show
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:89:71:6b:33 brd ff:ff:ff:ff:ff:ff
7: veth7a11ca8@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
link/ether f2:a4:a4:4d:5e:4e brd ff:ff:ff:ff:ff:ff link-netnsid 0
9: veth33f3a68@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default
link/ether 9a:52:69:c4:5f:73 brd ff:ff:ff:ff:ff:ff link-netnsid 1
# docker0默认是SNAT桥
iptables -t nat -vnL
Chain POSTROUTING (policy ACCEPT 20 packets, 1498 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
docker的四种网络模型
![](https://img.haomeiwen.com/i14021735/e02397104639d0a3.png)
# 查看bridge的详细信息
docker network inspect bridge
# 可以在创建容器时指定主机名和网络, 挂载的文件系统和pid
docker contain run --help
-h, --hostname string Container host name
--network network Connect a container to a network
--mount mount Attach a filesystem mount to the container
--pid string PID namespace to use
docker容器网络
手动操作名称空间
- 利用ip命令和网络名称空间模拟虚拟机上的网络, 可用于测试
yum -y install iproute
# ip命令可以操作netns对象
ip netns help
Usage: ip netns list
ip netns add NAME
ip netns set NAME NETNSID # 设置网络名称空间的SID
ip [-all] netns delete [NAME]
# 删除ns时会将其中的虚拟网卡(包括另一块网卡)一同删除
ip netns identify [PID]
ip netns pids NAME
ip [-all] netns exec [NAME] cmd ... # 在网络名称空间中执行命令
ip netns monitor
ip netns list-id
ip netns add r1 # 新建网络名称空间r1
ip netns add r2 # 新建网络名称空间r2
ip netns list
ip netns exec r1 ifconfig -a # 此时netns中均没有除lo外的网卡
ip netns exec r2 ifconfig -a
lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# 创建虚拟网卡对, veth: 虚拟以太网网卡
ip link add name veth1.1 type veth peer name veth1.2
# 这对虚拟网卡的一块名为veth1.1, 另一块作为它的同伴名为veth1.2
ip link show
ifconfig # 因新建的虚拟网卡对默认没有被激活, 此处无法显示
# 将新建的虚拟网卡对中的veth1.2挪到网络名称空间r1中, 挪过去之后默认没有被激活
ip link set dev veth1.2 netns r1
# 此时veth1.1留在宿主机中, 相当于宿主机上有一块虚拟网卡与r1上的网卡连接
ip netns exec r1 ifconfig -a # 可以查看到挪过来的veth1.2
ip netns exec r1 ip link set dev veth1.2 name eth0 # 可以将r1中的veth1.2改名为eth0
# 可以将这对网卡分别激活
ifconfig veth1.1 10.1.0.1/24 up # 激活宿主机侧虚拟网卡
ip netns exec r1 ifconfig eth0 10.1.0.2/24 up # 激活网络名称空间r1侧虚拟网卡
ping 10.1.0.2 # 用宿主机侧虚拟网卡ping r1中的虚拟网卡, 此时网络联通
# 也可以将veth1.1挪至r2中
ip link set dev veth1.1 netns r2
ip netns exec r2 ifconfig veth1.1 10.1.0.3/24 up
# 此时r1上的veth1.2和r2上的veth1.1可以互ping, 说明网络联通
ip netns exec r1 ping 10.1.0.3
![](https://img.haomeiwen.com/i14021735/18e9d617b72e016e.png)
开放网络实现端口暴露
inbound: n. 入站 adj. 入境的; 归本国的; 回内地的
![](https://img.haomeiwen.com/i14021735/1b39a9438a9c3052.png)
![](https://img.haomeiwen.com/i14021735/6326466a9c9c044e.png)
docker contain run --name myweb --rm -p 80 busybox:latest
# 暴露出了容器myweb上的80端口, 但映射到宿主机上的端口随机
iptable -t nat -nvL
# 此时做了一个DNAT, 外部可以访问宿主机的对应随机端口, 被转发至虚拟机的80端口
curl 172.20.0.67:32769
# 可自行指定宿主机上的启动端口
docker port myweb # 显示指定容器上的端口映射
docker container run --name myweb --rm -p 172.20.0.67:80:80 busybox:latest
# 此处指定了宿主机ip172.20.0.67, 端口80映射到容器的80端口
# 而不是宿主机的0.0.0.0 (所有可用地址)上的80端口映射到容器的80端口
联盟式容器
- 让两个容器共享同一个网络名称空间
- 实质是共享IPC, Net, UTS, 但各自的PID, Mount, User还是独立的
![](https://img.haomeiwen.com/i14021735/c9d4707a08858527.png)
容器间网络共享
docker container run --name b1 -it busybox
docker container run --name b2 --nerwork container:b1 -it busybox
# b2共享b1的网络名称空间, 但两者的文件系统等还是隔离的
# 此时两者的ip相同, 可用ipconfig测试
# 但两者的文件系统还是隔离的, 可测试:
# b1上ls /tmp和b2上ls /tmp, 其中的内容不同
容器与宿主机间网络共享
docker container run --name b2 --nerwork host -it busybox # 直接共享宿主机的网络空间
ifconfig # 验证, 会发现容器的ip地址与宿主机的ip地址相同
自定义默认docker0桥网络信息
![](https://img.haomeiwen.com/i14021735/dac0a1e66b075cc8.png)
- 修改完之后重启docker服务, 使自定义网络信息生效
如何使用docker远程连接其他docker daemon
- 默认不可以远程连接控制, 需要开启配置
- 本地控制: 默认使用unix的套接字
/var/run/docker.socket
- 外部docker控制: 需要在
/etc/docker/daemon.json中添加hosts项的tcp连接
![](https://img.haomeiwen.com/i14021735/47e36c3291bccb03.png)
docker -H 172.20.0.67:2375 ps # 本地可以远程控制ip:port为172.20.0.67:2375的远端docker服务
docker -H 172.20.0.67:2375 image ls
如何创建自定义桥
docker info | grep Network # 查看docker支持的网络插件
Network: bridge host ipvlan macvlan null overlay
docker network create [OPTIONS] NETWORK
dockere network create -d bridge \
--subnet "172.26.0.0/16" \
--gateway "172.26.0.1" \
mybr0
docker network ls
ifconfig # 注意, 自定义的网桥名称和新建的网络接口名称不一致, 可以改名
ip link set dev br-3291c2ff6eb name docker1
# 新建容器时加入mybr0的网路
docker container run --name t1 -it --network mybr0 busybox:latest
# 两个不同网段的容器间通信, 需要在宿主机上开启ip_forward
echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.d/ip_forward.conf
网友评论