Docker 容器网络

Docker 容器网络

网络只不过是一个区域【数据交流】

  • 默认情况下,所有容器都运行在 Docker 默认的网络空间中。
  • 在默认网络中,每个容器都可以与其他容器通信,我们可以创建网络隔离。

Docker 网络类型

一般情况,分三种:

  • none:对于这个容器,禁用所有网络
  • host:对于独立容器,直接使用宿主机的网络
  • bridge:配置桥接网络,桥接网络使用软件桥接,允许连接到同一桥接网络的容器进行通信,同时提供与未连接到该桥接网络的容器的隔离。默认使用的网络模式【启动 Docker 时,会自动创建一个默认的桥接网络】

默认桥接网络的一个缺点是不支持使用 DNS 自动发现容器服务。因此,如果您希望属于默认网络的容器能够相互通信,则必须使用 --link 选项静态允许通信发生。此外,通信需要容器之间的端口转发。

并采用的复杂配置模式:overlay, ipvlan, macvlan 三者分别覆盖网络、控制 IP、控制 MAC

开始测试前需要两个容器 container

  • 容器 A:docker run -dit --name c-a alpine ash
  • 容器 B:docker run -dit --name c-b alpine ash

-it 应该都知道,-d 是挂后台的意思

  • alpine 镜像是基于 Alpine Linux 的最小 Docker 镜像,一般进行测试使用
  • ash 是 shell,属于 Bourne shell 简化版本,特点是占用系统资源最少,感兴趣可以去学习,不过主流是 bash, zsh

上面在创建时,并没有什么特别的,根据默认创建那么它们应该是使用相同给默认桥接网络

learn@debian10:~/work$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c8e2262fa6ef bridge bridge local
5050dfe48c19 host host local
ac4d3767e763 none null local

默认 bridge 网络的名称也是 bridge,追查 c8e2262fa6ef 网络,就是默认 bridge 那个使用 docker network inspect <network-name|network-id>

learn@debian10:~/work$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "c8e2262fa6ef5bf351c325efe2bebf715c8174641ee3be711e2989aed13c8803",
"Created": "2023-04-09T20:35:16.356724826+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": {
"83358fcb0195b367b553d7bb610d09a0f64bdbf77afb4b55a2d2371e1b69c1e9": {
"Name": "c-b",
"EndpointID": "1e9a8d123a4b38af5119185318bc43214b64ea49c2edb197ec986f136ba44578",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"9fe00453457a633a650d049083cc85c39b6b55a617e2d3b49d86864a1231d7e7": {
"Name": "c-a",
"EndpointID": "8a69f2d9e54411358b79138b3c662185c27d6d689d9ea26d289c49a0c9a4f9b9",
"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": {}
}
]

Containers 属性是可以看到它连接的两个容器 c-ac-b

  • 网络配置中可以看到网关是 172.17.0.1
  • c-a 分配的 IPv4 是 172.17.0.2/16
  • c-b 分配的 IPv4 是 172.17.0.3/16

我们使用 docker attach <container-name> 连接容器

  • 说明这个子命令作用是将本地标准流附加到正在运行的容器
learn@debian10:~/work$ docker attach c-a
/ #

接下来我们使用的是 alpine 的 ash 作为 shell 不是 bash,我们已经进入 alpine 的 c-a 容器中

# 查看 c-a 中的网络接口,下面是完整命令,简化是 ip a
# 为什么没有使用 ifconfig,已经快淘汰 ...
ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 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
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
  • lo 是本地回环,学习过计算机网络应该都知道
  • eth0@if5 接口是连接 bridge 网络的网卡,其中的 172.17.0.2/16 是否眼熟 😋
  • 同样的方法可以在 c-b 中验证

注意网络接口和网卡说法是大致相同的

开始网络测试

  • 网络连通性测试工具 ping
  • 使用 -c 选项是设置测试次数,对于参数是正整数
# 测试公网
ping -c 4 baidu.com
PING baidu.com (39.156.66.10): 56 data bytes
64 bytes from 39.156.66.10: seq=0 ttl=49 time=24.285 ms
64 bytes from 39.156.66.10: seq=1 ttl=49 time=31.348 ms
64 bytes from 39.156.66.10: seq=2 ttl=49 time=23.836 ms
64 bytes from 39.156.66.10: seq=3 ttl=49 time=22.960 ms
--- baidu.com ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 22.960/25.607/31.348 ms
# 测试 c-b 容器
ping -c 4 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.217 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.305 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.392 ms
64 bytes from 172.17.0.3: seq=3 ttl=64 time=0.227 ms
--- 172.17.0.3 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.217/0.285/0.392 ms

用同样方法测试另一个容器,可以发现它们是网络互通的,并且默认 bridge 并非封闭的

如果你需要删除容器 c-a, c-b

  • docker container stop c-a c-b
  • docker container rm c-a c-b

如果你是学习,下面命令可以一次性全部删除 停止的容器

  • docker container prune

使用用户定义的桥接网络

创建一个我们自定义的 bridge 类型网络:test-net

  • 语法大体:docker network create --driver <net-type> <net-name>
  • --driver 选项设置网络类型,没有默认 bridge

开始实验:

# 创建网络 test-net
docker network create --driver bridge test-net
3477f402ce19f4f6d93eb2cd126040023151ec7fe50ddbd7ed8c824b75304b70
# 查看当前所有网络
docker network ls
NETWORK ID NAME DRIVER SCOPE
85af1da27cc7 bridge bridge local
5050dfe48c19 host host local
ac4d3767e763 none null local
3477f402ce19 test-net bridge local

通过 docker network inspect <net-name> 查看网络配置

learn@debian10:~/work$ docker network inspect test-net
[
{
"Name": "test-net",
"Id": "3477f402ce19f4f6d93eb2cd126040023151ec7fe50ddbd7ed8c824b75304b70",
"Created": "2023-04-10T18:40:36.149310552+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": {},
"Options": {},
"Labels": {}
}
]

其网关与之前默认网络的有所不同 172.18.0.1

我们布置三个容器

# c1 和 c2 容器设置为 test-net 网络
docker run -dit --name c1 --network test-net alpine ash
docker run -dit --name c2 --network test-net alpine ash
# c3 使用默认 bridge
docker run -dit --name c3 alpine ash

使用 docker network inspect <net-name> 检查 test-net 变化,像之前默认测试一样

learn@debian10:~/work$ docker network inspect test-net
[
{
"Name": "test-net",
"Id": "3477f402ce19f4f6d93eb2cd126040023151ec7fe50ddbd7ed8c824b75304b70",
"Created": "2023-04-10T18:40:36.149310552+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": {
"0e02f61d92676b14a1fefdc500b52d239e63717463f8b7994ed00752c3b975d6": {
"Name": "c1",
"EndpointID": "33289017f78d0a8bfda7339958a1b118ed2cb7a9a1c1e4bb1a2c2b8ad5558d7b",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"e4b657a0202f0d5bcc7b521c9c2b01910316b6dd8feb84bfad2667679fef457e": {
"Name": "c2",
"EndpointID": "b4c5b988276f73ea2aea06374191bd9ccb53bfe11fa22001680db062fe6c4d3c",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]

知道它们的 IPv4

  • c1: 172.18.0.2/16
  • c2: 172.18.0.3/16
  • c3: 172.17.0.2/16

之后分别进入其中进行测试

  • c1 与 c2 连通
  • c1 与 c3 阻塞
  • c2 与 c3 阻塞

网络成功实现隔离,其实学习过计算机网络看 IP 地址分块也应该知道它们不在同一个网络中。

一个新手比较感兴趣的问题:使用代理

通过设置环境变量就可以实现,在构建镜像或创建容器时设置环境变量 HTTP_PROXYHTTPS_PROXY 就可以

比如:你代理是 https://192.168.1.12:3128 使用 docker run -dit alpine ash --env HTTPS_PROXY="https://192.168.1.12:3128" 就可以了

这只是 Docker 网络的一小部分,如果需要进一步深入 👉 https://docs.docker.com/network/

posted @   sha0dow  阅读(329)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示