06-docker网络模式
06-docker网络模式

Docker网络
我们使用容器,不但是运行单机程序,当然是需要运行网络服务在容器中,那么如何配置docker的容器网络,基础网络配置,网桥配置。
docker 网络功能
docker的网络功能就是利用Linux的network namespace,network bridge,虚拟网络设备实现的。
在默认的情况下docker安装完毕后会生成网桥docker0,可以理解为一个虚拟的交换机,对两端的数据进行发送
docker的网络接口默认都是虚拟网络接口
docker容器网络在宿主机和容器内分别创建一个虚拟接口,让他们彼此通信
[root@docker-200 /www.yuchaoit.cn/harbor]#ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:3eff:feca:fa2b prefixlen 64 scopeid 0x20<link>
ether 02:42:3e:ca:fa:2b txqueuelen 0 (Ethernet)
RX packets 180132 bytes 9772747 (9.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 289156 bytes 448238750 (427.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@docker-200 /www.yuchaoit.cn/harbor]#
docker创建一个容器流程
- 创建一对虚拟接口,分别放到本地主机和新容器中
- 宿主机一端桥接到默认的docker0,且有一个唯一的名字
- 另一端放入容器里,改名为eth0该接口只能在容器的命名空间里可见
- 从网桥可用地段获取一个空闲的ip,分配给容器eth0,且默认路由桥接到宿主机网卡
- 这些完后,容器可以使用eth0虚拟网卡和其他容器相连接
docker run 启动时候,若没有添加--net参数,默认使用bridge桥接模式
docker实际是通过iptables做了dnat规则
docker网络图解
首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包,此外,如果不通子网之间需要进行通信,需要路由机制
Docker中网络接口默认都是虚拟接口,虚拟接口的优势是效率转发高
Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做 veth pair)。

接下来的部分将介绍在一些场景中,Docker所有的网络制定配置,以及通过Linux命令来进行调整,补充,甚至通过替换Docker默认网络配置
关于docker网络相关命令
下面是一个跟 Docker 网络相关的命令列表。
其中有些命令选项只有在 Docker 服务启动的时候才能配置,而且不能马上生效。
-b BRIDGE 或 --bridge=BRIDGE 指定容器挂载的网桥
--bip=CIDR 定制 docker0 的掩码
-H SOCKET... 或 --host=SOCKET... Docker 服务端接收命令的通道
--icc=true|false 是否支持容器之间进行通信
--ip-forward=true|false 请看下文容器之间的通信
--iptables=true|false 是否允许 Docker 添加 iptables 规则
--mtu=BYTES 容器网络中的 MTU
下面2个命令选项既可以在启动服务时指定,也可以在启动容器时指定。在 Docker 服务启动的时候指定则会成为默认值,后面执行 docker run 时可以覆盖设置的默认值。
--dns=IP_ADDRESS... 使用指定的DNS服务器
--dns-search=DOMAIN... 指定DNS搜索域
最后这些选项只有在 docker run 执行时使用,因为它是针对容器的特性内容。
-h HOSTNAME 或 --hostname=HOSTNAME 配置容器主机名
--link=CONTAINER_NAME:ALIAS 添加到另一个容器的连接
--net=bridge|none|container:NAME_or_ID|host 配置容器的桥接模式
-p SPEC 或 --publish=SPEC 映射容器端口到宿主主机
-P or --publish-all=true|false 映射容器所有端口到宿主主机
容器访问控制
容器的访问控制,主要是通过Linux上的iptables防火墙来进行管理和实现
iptables是Linux上默认的防火墙,在大部分的发行版中自带的。
容器访问外部网络
容器要想访问外部网络,需要本地系统的转发支持,在linux检查是否打开
$sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
如果为 0,说明没有开启转发,则需要手动打开。
$sysctl -w net.ipv4.ip_forward=1
如果在启动 Docker 服务的时候设定 --ip-forward=true, Docker 就会自动设定系统的 ip_forward 参数为 1。
容器之间访问
容器之间相互访问,需要两方面支持
容器的网络是否连接到互联网
默认情况下,所有容器都会被链接到docker0网桥上
要看本地系统的防火墙软件-iptables是否允许通过
1.Docker4种网卡模式(面试要问)
–net参数
--net=bridge 这个是默认值,连接到默认的网桥Docker0,这个模式给容器自动分配ip,且通过iptables的nat表和宿主机实现数据通信
--net=host 告诉docker不要将容器网络放在隔离的命名空间中,不要容器化容器内的网络,此时容器使用本地主机网络,他完全拥有本地主机接口和访问权限容器进程可以跟主机其他root进程一样可以打开范围端口,可以访问本地网络服务还可以让容器影响整个主机系统的事情,比如重启主机因此使用这个选项时要非常小心。
--net=container container-->容器id
将新建容器的进程放到一个已经存在的网络栈中,新容器进程有自己的文件系统,但会和已存的容器共享ip地址和端口等网络资源。
--net=none 让docker容器不进行网络配置
查看docker的网络模式
查看当前docker已有的网络配置
[root@docker-200 ~]#docker network ls
NETWORK ID NAME DRIVER SCOPE
6cb9ed4cc353 bridge bridge local
6d71aada2627 harbor_harbor bridge local
f3971eca0c0f host host local
ff6208d689fb none null local
查看docker0默认网桥
[root@docker-200 ~]#ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:3eff:feca:fa2b prefixlen 64 scopeid 0x20<link>
ether 02:42:3e:ca:fa:2b txqueuelen 0 (Ethernet)
RX packets 182668 bytes 9877642 (9.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 292481 bytes 473496962 (451.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@docker-200 ~]#
# 安装网桥管理工具
[root@docker-200 ~]#yum install bridge-utils -y
[root@docker-200 ~]#brctl show
bridge name bridge id STP enabled interfaces
br-6d71aada2627 8000.02420be0d11c no veth074229e
docker0 8000.02423ecafa2b no
查看端口映射与防火墙的关系

2.bridge模式
容器桥接网络原理
1. 当docker daemon第一次启动后,创建了一个虚拟的网桥,名字是docker0
2. 创建后,给这个网桥,默认分配一个子网,默认是172.17.0.1/16
3. 每创建一个容器,都自动创建一个veth设备对儿,一个关联docker0,另一端挂载容器里,叫做eth0,并且从网桥的地址段里,分配一个ip给容器,因此实现通信。
[root@docker-200 /etc/sysconfig/network-scripts]#docker inspect ff9|grep -i '"IPAddress"'
"IPAddress": "172.17.0.2",
"IPAddress": "172.17.0.2",
桥接网络模式特点
1. 同一个宿主机的容器可以相互连接,不同宿主机的不可以(iptables也不在一个机器么)
2.桥接模式的容器自动获取172.17.0.0/16网段的IP地址
[root@7dc8c7225862 /]# ifconfig |grep 172
inet 172.17.0.5 netmask 255.255.0.0 broadcast 172.17.255.255
3.其他机器无法直接访问容器,需要通过端口映射。
4.每个容器映射到宿主机的端口,也唯一
5.容器可以借助宿主机的网络环境,访问其他机器。
桥接数据图

查看bridge模式详情
[root@docker-200 /etc/sysconfig/network-scripts]#docker network inspect bridge |jq
[
{
"Name": "bridge",
"Id": "6cb9ed4cc353820c6753626de168b20dcf3d86ee3e6284318a98dac10d1a6864",
"Created": "2022-08-27T22:02:43.680182817+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"bf84dad09ba34fd27dc3c743532c62227a104c38a8bc05cd89197f7507b7c12c": {
"Name": "crazy_bartik",
"EndpointID": "305fb33cef0514efb339ac3e7da0415c4bd382aab3b3db5923a7261a0d70ec80",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"d7ebdcb6d7fa45c8fc4e202bfb0bb049626166ff5e72453af69929e365ffc57e": {
"Name": "infallible_cohen",
"EndpointID": "51afb25f958f72f9c8c21b72779c3a36dab40953fdd74d58eb9b912a5e7cb4f7",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
},
"ff9990f7e1f5fb14b486e59ad4087e9bf8ddd61a4d8cfdd5ff66b7036df75b08": {
"Name": "gifted_hawking",
"EndpointID": "c14577fa81212e1824bfcaccf45a85d5b85a64b81f02e35e41bfa08a8cbdd0ba",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
[root@docker-200 /etc/sysconfig/network-scripts]#docker network inspect bridge |jq
基于busybox容器调试网络
默认其他镜像,都没有网络工具,要就自己定义
调试工具王者 busybox
[root@docker-200 /etc/sysconfig/network-scripts]#docker run -it busybox /bin/sh
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
5cc84ad355aa: Pull complete
Digest: sha256:5acba83a746c7608ed544dc1533b87c737a0b0fb730301639a0179f9344b1678
Status: Downloaded newer image for busybox:latest
/ # cd
~ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:05
inet addr:172.17.0.5 Bcast:172.17.255.255 Mask:255.255.0.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:8 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:648 (648.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
~ # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
~ # ping 10.0.0.200 -c 3
PING 10.0.0.200 (10.0.0.200): 56 data bytes
64 bytes from 10.0.0.200: seq=0 ttl=64 time=0.115 ms
64 bytes from 10.0.0.200: seq=1 ttl=64 time=0.079 ms
64 bytes from 10.0.0.200: seq=2 ttl=64 time=0.152 ms
--- 10.0.0.200 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.079/0.115/0.152 ms
~ # traceroute 10.0.0.200
traceroute to 10.0.0.200 (10.0.0.200), 30 hops max, 46 byte packets
1 10.0.0.200 (10.0.0.200) 0.012 ms 0.010 ms 0.009 ms
若是遇见要自定义容器网段的需求
Docker服务默认会创建一个docker0网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。
Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU(接口允许接收的最大传输单元),通常是 1500 Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置。
3.host模式
1. hosts启动的容器,没有自己的网卡,ip信息,直接用宿主机的
2. 但是除了network网络空间,其他如进程,文件系统,还是容器自己的
3. 通过参数 --network host 开启
4. host模式,没有端口映射功能
5.直接使用宿主机的网络环境,因此网络性能更高一筹。
host模式实战
1.看看宿主机端口
[root@docker-200 /www.yuchaoit.cn]#netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1021/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1254/master
tcp6 0 0 :::22 :::* LISTEN 1021/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1254/master
[root@docker-200 /www.yuchaoit.cn]#
2.运行容器
[root@docker-200 /www.yuchaoit.cn]#docker run -d --network host nginx
3.查看端口,进程,即可分析出host模式的原理
4. 访问容器nginx
10.0.0.200
5.修改容器内nginx页面
[root@docker-200 /www.yuchaoit.cn]#docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c4364027e26b nginx "/docker-entrypoint.…" 2 minutes ago Up 2 minutes clever_bell
[root@docker-200 /www.yuchaoit.cn]#docker exec -it clever_bell bash
cat >/etc/apt/sources.list <<'EOF'
deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ trusty-backports main restricted universe multiverse
EOF
6.更新容器内信息
apt update
root@docker-200:/# apt install iproute2 net-tools -y
查看容器内网络信息,而然看到的是宿主机的网络配置
ifconfig

4.container模式

实战
1.准备一个容器
[root@docker-200 /www.yuchaoit.cn]#docker run -it --name expose-80 -p 80:80 centos:7.6.1810
[root@3739c811d393 /]#
[root@3739c811d393 /]# curl 127.0.0.1
curl: (7) Failed connect to 127.0.0.1:80; Connection refused
2.再来一个容器
[root@docker-200 ~]#
[root@docker-200 ~]#docker run -d --name to_nginx --network container:expose-80 nginx
10e9d3472f7254db2e9790d4e01a97d617321e8226ef35dd8be763a2b5077ba4
[root@docker-200 ~]#
[root@docker-200 ~]#
3.宿主机测试
[root@docker-200 ~]#docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)
/to_nginx -
/expose-80 - 192.168.2.2
[root@docker-200 ~]#
4.查看nginx结果
[root@docker-200 ~]#curl -I 192.168.2.2
HTTP/1.1 200 OK
Server: nginx/1.21.5
Date: Sat, 27 Aug 2022 15:39:35 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 28 Dec 2021 15:28:38 GMT
Connection: keep-alive
ETag: "61cb2d26-267"
Accept-Ranges: bytes
[root@docker-200 ~]#
5.None模式
这个模式正常几乎不用
6.自定义网络模式
1.例如自定义创建一个网桥,分配一个子网,使用该网桥的容器互相之间,可以直接通信
2.创建自定义网络语法
docke network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名字>
# 引用自定义网络
docker run --network <自定义网络名> <镜像名>
# 删除自定义网络
docker network rm <自定义网络名>
实践
1. 创建自定义网络
docker network create -d bridge --subnet 192.168.55.0/24 --gateway 192.168.2.1 www.yuchaoit.cn_net
2.查看自定义网络
[root@docker-200 ~]#docker network create -d bridge --subnet 192.168.55.0/24 --gateway 192.168.55.1 www.yuchaoit.cn_net
9e2641d14fcad4c5b0e4000a16df68affeb198476d5472a8d40665e34bd5e0cc
[root@docker-200 ~]#docker network ls
NETWORK ID NAME DRIVER SCOPE
2c43f9897ff2 bridge bridge local
6d71aada2627 harbor_harbor bridge local
f3971eca0c0f host host local
ff6208d689fb none null local
9e2641d14fca www.yuchaoit.cn_net bridge local
3.查看网卡情况
[root@docker-200 ~]#ip addr show br-9e2641d14fca
317: br-9e2641d14fca: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:1d:cc:79:81 brd ff:ff:ff:ff:ff:ff
inet 192.168.55.1/24 brd 192.168.55.255 scope global br-9e2641d14fca
valid_lft forever preferred_lft forever
[root@docker-200 ~]#
4.查看宿主机的网桥
[root@docker-200 ~]#brctl show
bridge name bridge id STP enabled interfaces
br-6d71aada2627 8000.02420be0d11c no
br-9e2641d14fca 8000.02421dcc7981 no
docker0 8000.02423ecafa2b no
5.创建容器,用自建的网桥
[root@docker-200 ~]#
[root@docker-200 ~]#docker run --name busybox_myself_net -it --network www.yuchaoit.cn_net busybox /bin/sh
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:C0:A8:37:02
inet addr:192.168.55.2 Bcast:192.168.55.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:946 (946.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ # ping 10.0.0.200
PING 10.0.0.200 (10.0.0.200): 56 data bytes
64 bytes from 10.0.0.200: seq=0 ttl=64 time=0.264 ms
64 bytes from 10.0.0.200: seq=1 ttl=64 time=0.139 ms
^C
--- 10.0.0.200 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.139/0.201/0.264 ms
/ #
/ #
/ # route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.55.1 0.0.0.0 UG 0 0 0 eth0
192.168.55.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
/ #
/ #
/ # traceroute 10.0.0.200
traceroute to 10.0.0.200 (10.0.0.200), 30 hops max, 46 byte packets
1 10.0.0.200 (10.0.0.200) 0.014 ms 0.009 ms 0.008 ms
/ #
6.再运行第二个容器,查看2个容器的网络连接性
docker run --name busybox2_myself_net -it --network www.yuchaoit.cn_net busybox /bin/sh
7.容器之间可以通过主机名通信
ping busybox2_myself_net -c 2
ping busybox_myself_net -c 2
提取容器ip地址
1. 进入容器内部后
cat /etc/hosts
会显示自己以及(– link)软连接的容器IP
2.使用命令
docker inspect <container id>
或
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id
3.要获取所有容器名称及其IP地址只需一个命令。
docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)
如果使用docker-compose命令将是:
docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
4.显示所有容器IP地址:
docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
-----------------------------------------------------------------------------------------------
经验:可以考虑在 ~/.bashrc 中写一个 bash 函数:
function docker_ip() {
sudo docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $1
}
function dockeriplist() {
sudo docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
}
执行docker_ip <container-ID>可以看到单个容器的IP
执行dockeriplist 可以列出所有的IP
更多推荐



所有评论(0)