docker网络主要解决如下问题
#连接一个容器到一个网络
docker network connect Connect a container to a network
#创建一个网络
docker network create Create a network
#将容器从一个网络中断开
docker network disconnect Disconnect a container from a network
#查看网络的详细信息
docker network inspect Display detailed information on one or more networks
#查看网络列表
docker network ls List networks
#移除所有未使用的网络
docker network prune Remove all unused networks
#移除一个或多个网络
docker network rm Remove one or more networks
# 将容器中tcp端口80映射到主机8080端口
-p 8080:80
# 将容器中tcp端口80映射到地址192.168.239.154:8080
-p 192.168.239.154:8080:80
# 将容器中的udp端口80映射到主机8080端口
-p 8080:80/udp
# 将容器中的udp端口80映射到主机的udp端口8080
# 将容器中的tcp端口80映射到主机的tcp端口8080
-p 8080:80/tcp -p 8080:80/udp
docker run -d --rm --name mynginx1 -p 8081:80 --hostname mynginx1.test.com
nginx:1.23.4
curl http://localhost:8081
docker安装后会自动设置iptables规则来管理网络流量。这是docker网络核心部分之一
iptables由上而下,由Tables,Chains,Rules组成。
iptables有Filter, NAT, Mangle, Raw四种内建表:
Filter是iptables的默认表,它有以下三种内建链(chains):
INPUT链 – 处理来自外部的数据
OUTPUT链 – 处理向外发送的数据。
FORWARD链 – 将数据转发到本机的其他网卡设备上。
NAT表有三种内建链:
PREROUTING链 – 处理刚到达本机并在路由转发前的数据包。它会转换数据包中的目标IP地址(destination ip address),通常用于DNAT(destination NAT)。
POSTROUTING链 – 处理即将离开本机的数据包。它会转换数据包中的源IP地址(source ip address),通常用于SNAT(source NAT)。
OUTPUT链 – 处理本机产生的数据包。
Mangle表用于指定如何处理数据包。它能改变TCP头中的QoS位。Mangle表具有5个内建链(chains):
Raw表用于处理异常,它具有2个内建链:
PREROUTING chain
OUTPUT chain
规则的关键知识点:
Rules包括一个条件和一个目标(target)
如果满足条件,就执行目标(target)中的规则或者特定值。
如果不满足条件,就判断下一条Rules
在target里指定的特殊值:
[root@localhost gpt-data]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy DROP)
target prot opt source destination
DOCKER-USER all -- anywhere anywhere
DOCKER-ISOLATION-STAGE-1 all -- anywhere anywhere
ACCEPT all -- anywhere anywhere ctstate RELATED,ESTABLISHED
DOCKER all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:http
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target prot opt source destination
DROP all -- anywhere anywhere
RETURN all -- anywhere anywhere
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere
[root@localhost gpt-data]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242832fe5ed no veth861b463
vetha32efdf
使用网桥驱动创建网络options
选项 | 默认值 | 描述 |
---|---|---|
com.docker.network.bridge.name | 创建Linux网桥时要使用的接口名称 | |
com.docker.network.bridge.enable_ip_masquerade | true | 是否启用IP伪装,即将容器的IP地址转换成宿主机的ip地址进行网络访问,从而实现容器访问外部网络的功能,即容器对外部网络访问的权限等同宿主机 |
com.docker.network.bridge.enable_icc | true | 启用或禁用容器间连接(不是DNS解析) |
com.docker.network.bridge.host_binding_ipv4 | 0.0.0.0 | 绑定容器端口时的默认IP |
com.docker.network.driver.mtu | 0(不限制) | 设置容器最大传输单元 |
com.docker.network.container_iface_prefix | eth | 容器接口自定义前缀 |
docker network ls
route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.74.18.1 0.0.0.0 UG 104 0 0 eth0
10.74.18.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
所有以172.17开头并且子网掩码为255.255.0.0的IP地址的数据包都会被发送到docker0网桥
docker安装后悔自动设置iptables规则来管理网络流量。查看filter表
[root@localhost gpt-data]# iptables -t filter --line-numbers -L -n -v | column -t
Chain INPUT (policy ACCEPT 10M packets, 2480M bytes)
num pkts bytes target prot opt in out source destination
Chain FORWARD (policy DROP 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 2309 8646K DOCKER-USER all -- any any anywhere anywhere
2 2309 8646K DOCKER-ISOLATION-STAGE-1 all -- any any anywhere anywhere
3 1194 8580K ACCEPT all -- any docker0 anywhere anywhere ctstate RELATED,ESTABLISHED
4 0 0 DOCKER all -- any docker0 anywhere anywhere
5 1115 66538 ACCEPT all -- docker0 !docker0 anywhere anywhere
6 0 0 ACCEPT all -- docker0 docker0 anywhere anywhere
Chain OUTPUT (policy ACCEPT 16M packets, 2444M bytes)
num pkts bytes target prot opt in out source destination
Chain DOCKER (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT tcp -- !docker0 docker0 anywhere 172.17.0.2 tcp dpt:http
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
num pkts bytes target prot opt in out source destination
1 1115 66538 DOCKER-ISOLATION-STAGE-2 all -- docker0 !docker0 anywhere anywhere
2 2309 8646K RETURN all -- any any anywhere anywhere
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
num pkts bytes target prot opt in out source destination
1 0 0 DROP all -- any docker0 anywhere anywhere
2 1115 66538 RETURN all -- any any anywhere anywhere
Chain DOCKER-USER (1 references)
num pkts bytes target prot opt in out source destination
1 2309 8646K RETURN all -- any any anywhere anywhere
查看iptables nat表规则列表
[root@localhost docker]# iptables -t nat -L -n -v --line-numbers | column -t
Chain PREROUTING (policy ACCEPT 29 packets, 3391 bytes)
num pkts bytes target prot opt in out source destination
1 962 54116 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 21 packets, 1767 bytes)
num pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 1 packets, 60 bytes)
num pkts bytes target prot opt in out source destination
1 3 180 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 3 packets, 180 bytes)
num pkts bytes target prot opt in out source destination
1 49 3160 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
2 0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:80
3 0 0 MASQUERADE tcp -- * * 172.17.0.6 172.17.0.6 tcp dpt:80
Chain DOCKER (2 references)
num pkts bytes target prot opt in out source destination
1 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0
2 27 1620 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8081 to:172.17.0.2:80
3 74 4440 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:82 to:172.17.0.6:80
Chain POSTROUTING (policy ACCEPT 7697 packets, 516K bytes)
pkts bytes target prot opt in out source destination
49 3160 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0
0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:80
表示对于从不在docker0接口上的网络流量(即输出流量),如果源IP地址属于172.17.0.0/16网段,则进行伪装(MASQUERADE),将源IP地址替换为本机的外部IP地址,以实现网络地址转换(NAT)功能。这样可以确保来自172.17.0.0/16网段的数据包能够正确地回应到发起请求的主机
启容器
docker run -dit --rm --name alpine1 myalpine ash
docker run -dit --rm --name alpine2 myalpine ash
查看bridge网络
docker network inspect bridge
[
{
"Name": "bridge",
"Id": "52c18e3316468f9f14736d495029aa15b63473dbca0818b8ceab3f1d526dbac5",
"Created": "2023-12-26T11:26:27.150249598+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": {
"5c35cf3a8315d1477da3cd7693f83444af91d5a846007572cfc0c663c03c12a8": {
"Name": "alpine1",
"EndpointID": "46340efda036eda601504b5ca6928db7a098d3776bc77ff819921485156df026",
"MacAddress": "02:42:ac:11:00:04",
"IPv4Address": "172.17.0.4/16",
"IPv6Address": ""
},
"d9bd1dac57b716ad763d2cedc57ccb9de63e77074c6a16ba6b672cdec1c0cd1c": {
"Name": "alpine2",
"EndpointID": "fc082c335bb511f9518fa0c15fe717432b8c1b3b81d71e1bd3f6fc79620df7ee",
"MacAddress": "02:42:ac:11:00:05",
"IPv4Address": "172.17.0.5/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": {}
}
]
查看系统网络接口,会多出两张veth
ip ad
[root@localhost docker]# ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether fa:16:3e:30:2c:c0 brd ff:ff:ff:ff:ff:ff
inet 10.74.18.61/24 brd 10.74.18.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe30:2cc0/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:83:2f:e5:ed brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:83ff:fe2f:e5ed/64 scope link
valid_lft forever preferred_lft forever
309: vethf7628d0@if308: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 8a:ab:91:3a:0c:a7 brd ff:ff:ff:ff:ff:ff link-netnsid 2
inet6 fe80::88ab:91ff:fe3a:ca7/64 scope link
valid_lft forever preferred_lft forever
169: veth861b463@if168: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether c2:d4:57:7a:85:51 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::c0d4:57ff:fe7a:8551/64 scope link
valid_lft forever preferred_lft forever
185: vetha32efdf@if184: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether e6:4d:1a:49:65:15 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::e44d:1aff:fe49:6515/64 scope link
valid_lft forever preferred_lft forever
docker0网桥工作原理
默认桥接网络不提供dns解析,容器之间可以通过ip地址相互访问,但不能通过容器名称相互访问。可以使用自定义网络,将容器添加进网络,这样容器间就可以相互使用名字访问了
docker network create --driver bridge nginx-net
运行两个容器
docker run -d -p 8088:80 --network nginx-net --name nginx1 nginx
docker run -d -p 8089:80 --network nginx-net --name nginx2 nginx
# 查看nginx-net
[root@localhost docker]# docker inspect nginx-net
[
{
"Name": "nginx-net",
"Id": "b9bc42bfe03ffe38df86dd3b388d8d1ff58c1f8d5614ffe606191427fc6c5288",
"Created": "2024-01-03T14:47:57.506257705+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"3d22cf84216493e7fbb3a5ad773b8e77fc750a5aab356a06af083bff59944b5a": {
"Name": "nginx2",
"EndpointID": "3b47ad3fafebebee7acdc0243f0e0f3fac46b3039411fb46c6d62f8e292de6f4",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"e9c736a4ca090945fcee290614f491fe1fca5048b2d2b34fd78d878b96e88eba": {
"Name": "nginx1",
"EndpointID": "c2ecc9cecf7e8a1ae8c76fc2027feef1c169c9508a77ca382db63c2efd0362e3",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
两个容器之间可以使用容器名访问。容器网络,直接访问80端口
[root@localhost docker]# docker exec -it nginx1 bash
root@e9c736a4ca09:/# curl http://nginx2:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
# 将容器 nginx3 加入网络 nginx-net
docker network connect nginx-net nginx3
# 将容器 nginx4 加入网络 nginx-net
docker network connect nginx-net nginx4
# 查看网络详情
docker network inspect nginx-net
加入默认网络中的容器无法再不停服的情况下与docker0网桥断开
docker network disconnect nginx-net nginx1
docker network disconnect nginx-net nginx2
docker network disconnect nginx-net nginx3
docker network disconnect nginx-net nginx4
docker network rm alpine-net
docker network create \
--driver=bridge \
--subnet=172.28.0.0/16 \
--ip-range=172.28.5.0/24 \
--gateway=172.28.5.254 \
--opt com.docker.network.bridge.name=nginx-net1 \
--opt com.docker.network.bridge.enable_ip_masquerade=false \ #禁用IP伪装,无法访问外网
--opt com.docker.network.bridge.enable_icc=false \ #禁用容器间通讯
--opt com.docker.network.container_iface_prefix=ethtest \ # 网络接口前缀
nginx-net1
启动nginx后,外部机器无法访问首页(之前一直没啥问题)。查了下原因是因为ip转发未开启 net.ipv4.ip_forward=0
修改为1即可
sysctl -w net.ipv4.ip_forward=1
https://blog.51cto.com/u_14928887/3084685
https://zhuanlan.zhihu.com/p/629065642