1. 网络模式
1.1 网络结构
当安装Docker以后,会自动创建三个网络。可以使用docker network ls
命令列出这些网络。
shell
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
440aefe8afa3 bridge bridge local
aa8d6325580f host host local
3eb717ea6240 none null local
-
bridge
:桥接模式(默认),创建一个桥接网络,内部网卡自动获取IP地址,向外访问是经过NAT(网络地址转换)。 -
host
:不会创建出自己的网卡,和宿主机共享网络命名空间。即没有自己的IP,而是使用宿主机的IP和端口。 -
none
:不配置网络。需要时,进行自定义配置。
使用ip addr
查看系统网卡, 会多出一个网卡docker0
:
shell
$ ip addr
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:1d:9f:bd:cd 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
brctl show
查看网桥,系统已经创建一个网桥:
shell
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421d9fbdcd no
docker0
是一个网桥,可以把其他网卡加入,它工作在二层,可以理解是一个交换机
。每加入一个网卡,交换机便多一个口。当创建一个
Docker
容器的时候,同时会创建了一对veth pair
接口,两个接口相当于用网线直连。 这对接口其中一个在容器内
;另一个被加入到docker0
网桥中,名称以veth
开头。容器和主机可以通信,容器之间在一个局域里,也可以相互通信。Docker 创建了在主机和所有容器之间一个虚拟二层交换网络。
【创建容器并运行】
shell
docker run --name bjbook -p 8000:8000 -it --rm python:3 python -m http.server
这行命令使用 Docker 运行一个 Python 容器,并将其配置为一个简单的 HTTP 服务器。
解释:
docker run
: 运行一个 Docker 容器。--name bjbook
: 为容器命名为bjbook
。-p 8000:8000
: 将容器的 8000 端口映射到主机的 8000 端口。这意味着可以通过在浏览器中输入http://localhost:8000
来访问容器中的 HTTP 服务器。-it
: 以交互模式运行容器,并分配一个伪终端 (TTY)。这允许在容器中输入命令。--rm
: 容器退出后自动删除容器。python:3
: 使用 Python 3 镜像作为容器的基础镜像。python -m http.server
: 在容器中运行 Python 的http.server
模块,创建一个简单的 HTTP 服务器。
【查看网桥】
shell
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421d9fbdcd no vethd123cb3
发现网桥中增加了名称为 vethd123cb3
的网卡。
【进入到容器里,查看其网卡信息】
shell
$ docker exec -it bjbook bash
$ cat /proc/net/dev
$ cat /proc/net/fib_trie
172.17.0.2/16
1.2 Bridge模式
bridge模式,--net=bridge
(默认)
这是docker网络的默认设置,为容器创建独立的网络名字空间
,容器具有独立的网卡
等所有单独的网络栈, 是最常用的使用方式。在docker run启动容器的时候,如果不加--net参数,就默认采用这种网络模式。
安装完docker,系统会自动添加一个 供docker使用的网桥docker0,我们创建一个新的容器时,容器通过DHCP获取一个与docker0同网段的IP地址
, 并默认连接到docker0网桥
,以此实现容器与宿主机的网络互通。
【查看网络信息】
shell
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "47b1606e07c37288c76ad42e2798ac60d836954bdd77b2167c10633b5ba7ad1a",
"Created": "2022-11-28T11:24:09.381326089+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": {},
"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": {}
}
]
1.3 Host模式
host模式,--net=host
和 - - network host
作用相同。
这个模式下创建出来的容器,直接使用容器宿主机的网络名字空间
,例如网卡
和IP
都是和宿主机共用。 但容器的其他方面,如文件系统和进程等是和宿主机隔离的。
例如启动nginx服务,默认绑定在主机的80端口,不用创建端口映射。
shell
$ docker run --rm -d --network host --name my_nginx nginx
1f378ca055340e87b3072e8cb15390c9b45a2b47ce4ebc8ec6dcfdec3e0503d5
1.4 Container模式
指定新创建的容器和已经存在的一个容器共享
一个 Network Namespace,而不是和宿主机共享。
新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。 这样两个容器除了网络,其他的如文件系统和进程等是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
1.5 None模式
该模式Docker容器拥有自己的Network Namespace,但Docker容器没有任何网络配置
。
这个Docker容器没有网卡、IP地址等
信息。按需另外为Docker容器添加网卡、配置IP等。
none模式可以在容器创建时通过--network=none
来指定。或使用 --net=none
指定。
应用举例:
例如一些计算任务,写入磁盘,不需要网络的情况下使用。
2. 自定义网络
2.1 容器互联
在微服务部署的场景下,注册中心是使用服务名
来唯一识别微服务的,而我们上线部署的时候微服务对应的IP地址可能会改动
,所以我们需要使用容器名来配置容器间的网络连接。使用--link
可以完成这个功能。
首先不设置--link
的情况下,是无法通过容器名来进行连接的。centos02容器是可以直接ping通centos01的容器ip,但是无法ping通centos01的容器name:
shell
[root@haha ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c742968a290a 5d0da3dc9764 "/bin/bash" 9 seconds ago Up 8 seconds centos02
581740709b5e 5d0da3dc9764 "/bin/bash" 30 seconds ago Up 28 seconds centos01
[root@haha ~]#
[root@haha ~]# docker exec -it centos01 ip addr
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
34: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
[root@haha ~]#
[root@haha ~]# docker exec -it centos02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.102 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.135 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.137 ms
[root@haha ~]#
[root@haha ~]# docker exec -it centos02 ping centos01
ping: centos01: Name or service not known
添加参数 --link
,可以通过容器name进行连接。centos03容器link到centos01,所以centos03可以直接通过ping centos01的容器名去ping通,但是反过来centos01去ping centos03的容器名是ping不通的。
shell
[root@haha ~]# docker run -d -P -it --name centos03 --link centos01 5d0da3dc9764
a66f059fe26da45e5c59af03a2c33f429452a2dcf884ad5826fa0e3985ab3862
[root@haha ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a66f059fe26d 5d0da3dc9764 "/bin/bash" 7 seconds ago Up 5 seconds centos03
c742968a290a 5d0da3dc9764 "/bin/bash" 11 minutes ago Up 11 minutes centos02
581740709b5e 5d0da3dc9764 "/bin/bash" 11 minutes ago Up 11 minutes centos01
[root@haha ~]#
[root@haha ~]# docker exec -it centos03 ping centos01
PING centos01 (172.17.0.2) 56(84) bytes of data.
64 bytes from centos01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from centos01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from centos01 (172.17.0.2): icmp_seq=3 ttl=64 time=0.076 ms
^C
[root@haha ~]#
[root@haha ~]# docker exec -it centos01 ping centos03
ping: centos03: Name or service not known
--link
的原理就是在centos03容器的/etc/hosts
文件中添加了要去link的centos01容器的容器名和ip地址映射
。但是因为docker0不支持容器名访问,所以--link设置容器互连的方式也不再推荐使用了,更多地选择 自定义网络
。
2.2 docker network命令
docker network
常使用的命令:
shell
$ docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
创建网络:
shell
docker network create [OPTIONS] NETWORK_NAME
docker network create mynetwork
-d DRIVER
: 指定网络驱动程序。--subnet SUBNET
: 指定网络子网。--gateway GATEWAY
: 指定网络网关。--ip-range IP_RANGE
: 指定网络 IP 范围。
连接网络:
shell
# 将容器连接到网络
docker network connect [OPTIONS] NETWORK_NAME CONTAINER_NAME
docker network connect mynetwork mycontainer
--alias ALIAS
: 为容器分配一个别名。--ip IP_ADDRESS
: 为容器分配一个特定的 IP 地址。
断开网络:
shell
# 将容器从网络断开
docker network disconnect [OPTIONS] NETWORK_NAME CONTAINER_NAME
docker network disconnect mynetwork mycontainer
删除网络:
shell
docker network rm [OPTIONS] NETWORK_NAME
-f
: 强制删除网络,即使有容器连接到该网络。
查看网络:
shell
docker network ls [OPTIONS]
-f
: 仅显示正在使用的网络。--filter
: 过滤网络列表。
其他:
docker network inspect [OPTIONS] NETWORK_NAME
: 查看网络的详细信息。
一些额外的信息:
- 使用
docker network prune
命令删除未使用的网络。 - 使用
docker network update
命令更新网络的配置。 - 使用
docker network create --help
命令查看更多选项。
2.3 自定义网络
shell
docker network create --help
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which to copy the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
-d, --driver string
- 作用: 指定网络驱动程序。
- 说明: 此选项指定用于创建网络的网络驱动程序。可用的驱动程序包括
bridge
、overlay
、macvlan
等。
--gateway strings
- 作用: 指定主子网的 IPv4 或 IPv6 网关。
- 说明: 此选项指定网络的网关地址,用于路由到网络外部的流量。
--subnet strings
- 作用: 指定 CIDR 格式的子网,表示网络段。
- 说明: 此选项指定网络的子网,用于分配容器 IP 地址。
示例:
shell
[root@haha ~]$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
ed1c176a06d49da31969e229138ef5988a5fd9d2b2f2d2fc5ec1078be99a3d39
[root@haha ~]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
aa8a26ae1484 bridge bridge local
62cd016ed66a host host local
ed1c176a06d4 mynet bridge local
fc650e2a675e none null local
查看新创键的mynet详细信息:
使用自定义网络创建容器后,相同网络name下的容器,不管是通过容器IP还是容器name,都可以进行网络通信:
shell
# 创建两个使用相同自定义网络的容器
[root@haha ~]¥ docker run -d -P --name centos-net-01 --net mynet -it 5d0da3dc9764 /bin/bash
[root@haha ~]4 docker run -d -P --name centos-net-02 --net mynet -it 5d0da3dc9764 /bin/bash
[root@haha ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2511566dd5f3 5d0da3dc9764 "/bin/bash" 4 seconds ago Up 3 seconds centos-net-02
924e92107f64 5d0da3dc9764 "/bin/bash" 23 seconds ago Up 21 seconds centos-net-01
a66f059fe26d 5d0da3dc9764 "/bin/bash" 43 minutes ago Up 43 minutes centos03
c742968a290a 5d0da3dc9764 "/bin/bash" 54 minutes ago Up 54 minutes centos02
581740709b5e 5d0da3dc9764 "/bin/bash" 55 minutes ago Up 55 minutes centos01
# 测试容器互连
[root@haha ~]$ docker exec -it centos-net-01 ping centos-net-02
PING centos-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.689 ms
[root@haha ~]$ docker exec -it centos-net-01 ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.091 ms
2.4 不同网卡的容器互联
在没有使用connect命令的情况下,不同网络间的容器是无法进行网络连接的。
不同Docker网络之间的容器想要连接的话,需要把该容器注册
到另一个容器所在的网络上,使用docker connect
命令。
shell
docker network connect mynet centos01
connect设置成功后,我们可以看到新注册进来的容器信息:
连接测试:
shell
# centos-net-01 ping centos01,连接成功
[root@haha ~]$ docker exec -it centos-net-01 ping centos01
PING centos01 (192.168.0.4) 56(84) bytes of data.
64 bytes from centos01.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.183 ms
# centos01 ping centos-net-01,连接成功
[root@haha ~]$ docker exec -it centos01 ping centos-net-01
PING centos-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.135 ms
# 未连接到mynet的容器还是无法访问
[root@haha ~]$ docker exec -it centos-net-01 ping centos02
ping: centos02: Name or service not known
参考链接:
Docker网络详解