目录
前提条件
- 拥有docker环境,可参考:Docker的安装
- 掌握容器的使用,可参考:Docker容器的使用
- 掌握镜像的使用,可参考:Docker镜像的使用
Docker网络简介
容器网络指的是容器之间相互连接并通信的能力,或者与非 Docker 工作负载进行通信的能力。
容器默认启用网络功能,并且可以发起对外连接。一个容器并不知道它所连接的网络类型,也不清楚其对等节点是否也是 Docker 工作负载。一个容器只能看到带有 IP 地址、网关、路由表、DNS 服务以及其他网络详细信息的网络接口。也就是说,除非该容器使用 "none" 网络驱动程序。
用户自定义网络
你可以创建自定义的用户定义网络,并将多个容器连接到同一网络。一旦连接到用户定义网络,容器之间就可以使用容器 IP 地址或容器名称相互通信。
网络驱动
以下网络驱动程序是默认可用的,并提供核心网络功能:
驱动程序 | 描述 |
---|---|
bridge | 默认的网络驱动程序。当应用程序在容器中运行且需要与同一主机上的其他容器进行通信时,通常会使用桥接网络。 |
host | 消除容器与 Docker 主机之间的网络隔离。 |
none | 将容器与主机及其他容器完全隔离。 |
overlay | 覆盖网络可将多个 Docker 守护进程连接在一起。使 Swarm 服务和容器能够跨节点进行通信。 |
ipvlan | IPvlan 网络可对 IPv4 和 IPv6 寻址进行全面控制。 |
macvlan | 为容器分配一个 MAC 地址。使其在网络上看起来就像一个物理设备。 |
Docker网络命令
Docker网络命令可以通过命令查看docker network --help
,命令总结如下表
命令 | 说明 |
---|---|
docker network create | 创建一个网络 |
docker network ls | 查看所有网络 |
docker network rm | 删除指定网络 |
docker network prune | 清除未使用的网络 |
docker network connect | 使指定容器连接加入某网络 |
docker network disconnect | 使指定容器连接离开某网络 |
docker network inspect | 查看网络详细信息 |
Docker网络使用
查看网络
查看网络
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
921778a07746 bridge bridge local
5107ee4b4d9d host host local
2cf3b8606207 none null local
创建网络
创建网络
[root@localhost ~]# docker network create mynet
82f8ebf4f4411b5573cda103a1ff2d86d347c0f2ba8af8a205992efddc0051d8
再次查看网络
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
921778a07746 bridge bridge local
5107ee4b4d9d host host local
82f8ebf4f441 mynet bridge local
2cf3b8606207 none null local
连接到新网络
查看容器默认的连接的网络
# 查看运行的容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f16e0185235f test/mychangenginx:v1 "/docker-entrypoint.…" 2 hours ago Up 2 hours 0.0.0.0:95->80/tcp, [::]:95->80/tcp nginx-test1
fe352b7ad389 nginx "/docker-entrypoint.…" 26 hours ago Up 2 hours 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp nginx-test
# 查看f16容器使用的网络:NetworkID为"921778a07746315ccd5d2a1a31e52b740b5e9f8dd6ae9d5a5945e000e07cc6b5",就是上一步默认的docker network ls命令查到的第一个网络
[root@localhost ~]# docker inspect f16
...
"NetworkSettings": {
"Bridge": "",
"SandboxID": "2c34eabc30427a9d9d802cf92892ffb27bd98fdbd524cb9957f6849497936913",
"SandboxKey": "/var/run/docker/netns/2c34eabc3042",
"Ports": {
"80/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "95"
},
{
"HostIp": "::",
"HostPort": "95"
}
]
},
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "90c5fcbf605116992b3ab4a150cca86f5e61f71b72017f4d09644e3d96182a8b",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:03",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null,
"NetworkID": "921778a07746315ccd5d2a1a31e52b740b5e9f8dd6ae9d5a5945e000e07cc6b5",
"EndpointID": "90c5fcbf605116992b3ab4a150cca86f5e61f71b72017f4d09644e3d96182a8b",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DNSNames": null
}
}
}
}
]
[root@localhost ~]#
让容器加入新网络
# 查看镜像
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f16e0185235f test/mychangenginx:v1 "/docker-entrypoint.…" 2 hours ago Up 2 hours 0.0.0.0:95->80/tcp, [::]:95->80/tcp nginx-test1
fe352b7ad389 nginx "/docker-entrypoint.…" 26 hours ago Up 2 hours 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp nginx-test
# 让f16和fe3加入新建的mynet网络,在加入网络时可以通过--alias给容器起别名
[root@localhost ~]# docker network connect mynet nginx-test
[root@localhost ~]# docker network connect mynet nginx-test1 --alias web
再次查看网络
# 查看网络,有两个网络,添加了mynet,网络ID分别为
"NetworkID": "921778a07746315ccd5d2a1a31e52b740b5e9f8dd6ae9d5a5945e000e07cc6b5",
"NetworkID": "82f8ebf4f4411b5573cda103a1ff2d86d347c0f2ba8af8a205992efddc0051d8",
[root@localhost ~]# docker inspect f16
...
"NetworkSettings": {
"Bridge": "",
"SandboxID": "2c34eabc30427a9d9d802cf92892ffb27bd98fdbd524cb9957f6849497936913",
"SandboxKey": "/var/run/docker/netns/2c34eabc3042",
"Ports": {
"80/tcp": [
{
"HostIp": "0.0.0.0",
"HostPort": "95"
},
{
"HostIp": "::",
"HostPort": "95"
}
]
},
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "90c5fcbf605116992b3ab4a150cca86f5e61f71b72017f4d09644e3d96182a8b",
"Gateway": "172.17.0.1",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"MacAddress": "02:42:ac:11:00:03",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"MacAddress": "02:42:ac:11:00:03",
"DriverOpts": null,
"NetworkID": "921778a07746315ccd5d2a1a31e52b740b5e9f8dd6ae9d5a5945e000e07cc6b5",
"EndpointID": "90c5fcbf605116992b3ab4a150cca86f5e61f71b72017f4d09644e3d96182a8b",
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DNSNames": null
},
"mynet": {
"IPAMConfig": {},
"Links": null,
"Aliases": [
"web"
],
"MacAddress": "02:42:ac:12:00:03",
"DriverOpts": {},
"NetworkID": "82f8ebf4f4411b5573cda103a1ff2d86d347c0f2ba8af8a205992efddc0051d8",
"EndpointID": "fba56ae8c5e008b5612a414160b0b7b311291a59578c074b2c931e67238b3361",
"Gateway": "172.18.0.1",
"IPAddress": "172.18.0.3",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"DNSNames": [
"nginx-test1",
"web",
"f16e0185235f"
]
}
}
}
}
]
[root@localhost ~]#
ping测试联通
为了方便测试,这里使用自带有ping命令的busybox镜像。
BusyBox 是一个集成了三百多个最常用Linux命令和工具的软件。BusyBox 包含了一些简单的工具,例如ls、cat和echo等等,还包含了一些更大、更复杂的工具,例grep、find、mount以及telnet。有些人将 BusyBox 称为 Linux 工具里的瑞士军刀。简单的说BusyBox就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令,也包含了 Linux 系统的自带的shell。
默认的网络
[root@localhost ~]# docker run -it --rm --name busybox0 busybox sh
/ # ping busybox0
ping: bad address 'busybox0'
/ # cat /etc/resolv.conf
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.
nameserver 114.114.114.114
nameserver 8.8.8.8
# Based on host file: '/etc/resolv.conf' (legacy)
# Overrides: []
/ # nslookup busybox0
Server: 114.114.114.114
Address: 114.114.114.114:53
** server can't find busybox0: NXDOMAIN
** server can't find busybox0: NXDOMAIN
/ #
1.
--rm
:当容器退出时,自动删除容器。这对于临时测试或运行一次性任务非常有用,避免了手动清理已退出的容器。2.ping busybox0不通,默认桥接网络主要关注的是容器的网络隔离和基本的 IP 地址分配,主要是为了提供基本的网络连接功能,使容器能够访问外部网络以及在同一主机上进行简单的通信。
3.查看resolv.conf,默认网络没有自动配置容器名称解析功能。
4.nslookup 是一个简单的命令行工具,用于查询 DNS 相关信息。在容器内部运行
nslookup
命令,后面跟上要查询的域名,就可以查看 DNS 解析过程,nslookup busybox0 查不到busybox0对应的ip地址,所以ping不通容器名。
在新的终端查看busybox0的ip
[root@localhost ~]# docker inspect --format='{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' busybox0
172.17.0.2
返回busybox0的终端,ping ip是可以的
/ # ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.047 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.089 ms
^C
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.047/0.068/0.089 ms
/ #
按ctrl+c返回busybox命令行
说明:默认网络ping容器名不通,只能ping通同一网段的ip。如果删除原有容器,重启启动新的容器,容器ip也会变化。如果容器用作数据库等中间件,ip变化就需要改动连接数据库的相关配置/代码,耦合性强。
自定义网络
新建的 my-net
网络
[root@localhost ~]# docker network create -d bridge my-net
-d 指定网络驱动类型
运行一个busybox容器并连接到 my-net
网络
[root@localhost ~]# docker run -it --rm --name busybox1 --network my-net busybox sh
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
a46fbb00284b: Pull complete
Digest: sha256:768e5c6f5cb6db0794eec98dc7a967f40631746c32232b78a3105fb946f3ab83
Status: Downloaded newer image for busybox:latest
/ #
打开新的终端,再运行一个容器并加入到 my-net
网络
[root@localhost ~]# docker run -it --rm --name busybox2 --network my-net busybox sh
/ #
再打开一个新的终端查看容器信息
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a9862423ff37 busybox "sh" 3 minutes ago Up 3 minutes busybox2
802c435c5041 busybox "sh" 3 minutes ago Up 3 minutes busybox1
[root@localhost ~]#
在 busybox1
命令行输入以下命令
/ # ping busybox2
PING busybox2 (172.20.0.3): 56 data bytes
64 bytes from 172.20.0.3: seq=0 ttl=64 time=0.166 ms
64 bytes from 172.20.0.3: seq=1 ttl=64 time=0.146 ms
64 bytes from 172.20.0.3: seq=2 ttl=64 time=0.141 ms
^C
--- busybox2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.141/0.151/0.166 ms
/ # ping 172.20.0.3
PING 172.20.0.3 (172.20.0.3): 56 data bytes
64 bytes from 172.20.0.3: seq=0 ttl=64 time=0.101 ms
64 bytes from 172.20.0.3: seq=1 ttl=64 time=0.161 ms
64 bytes from 172.20.0.3: seq=2 ttl=64 time=0.170 ms
^C
--- 172.20.0.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.101/0.144/0.170 ms
用 ping 来测试连接 busybox2
容器,它会解析成 172.19.0.3
。
同理在 busybox2
命令行执行 ping busybox1
,也会成功连接到。
/ # ping busybox1
PING busybox1 (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.056 ms
64 bytes from 172.20.0.2: seq=1 ttl=64 time=0.137 ms
64 bytes from 172.20.0.2: seq=2 ttl=64 time=0.146 ms
^C
--- busybox1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.056/0.113/0.146 ms
/ # cat /etc/resolv.conf
# Generated by Docker Engine.
# This file can be edited; Docker Engine will not make further changes once it
# has been modified.
nameserver 127.0.0.11
options ndots:0
# Based on host file: '/etc/resolv.conf' (internal resolver)
# ExtServers: [114.114.114.114 8.8.8.8]
# Overrides: []
# Option ndots from: internal
/ # nslookup busybox1
Server: 127.0.0.11
Address: 127.0.0.11:53
Non-authoritative answer:
Non-authoritative answer:
Name: busybox1
Address: 172.20.0.2
说明:
- 在连接到同一自定义网络的容器,它们之间ping ip或者ping 容器名是可以ping通的。
- 查看resolv.conf文件,
nameserver
行指定了 DNS 服务器的 IP 地址。127.0.0.11
是容器内部使用的 DNS 服务器地址,通常是 Docker 为容器配置的内部 DNS,配置了内部的DNS维护了容器名和ip地址的映射关系,这就是自定义网络可以ping 域名的原因。nslookup busybox1
会显示查询使用的 DNS 服务器以及域名对应的 IP 地址等信息,这里查看到busybox1对应的ip为172.20.0.2。
结论:默认网络,只能ping ip,自定义网络可以ping ip也可以ping 容器名,自定义网络会维护容器内部的DNS,所以可以ping容器名。因为各种原因容器被删除后,重启新的容器时容器名是可以不变的。这样如果容器作为数据库中间件,就直接使用容器名作为域名,就不需要改动连接数据库的相关配置/代码,降低了系统间的耦合。
完成!enjoy it!