Docker网络全方位解析
一、课程目标
本次Docker网络课程旨在达成两大核心目标,帮助学习者全面掌握Docker网络相关知识与实践技能:
- 深入理解Docker网络的不同类型,包括各类型网络的特性、适用场景及配置方式。
- 熟练掌握Docker容器之间的访问方式,以及容器与外部网络的交互方法,能够根据实际需求选择合适的网络方案实现容器通信与外部访问。
二、Docker网络类型
Docker在安装时会自动在Docker主机(Docker Host)上创建三种基础网络,我们可以通过执行docker network ls
命令查看这些网络。这三种网络分别是none网络、host网络和bridge网络,其中bridge网络是创建容器时默认使用的网络。
执行docker network ls
命令后,输出结果如下(示例):
NETWORK ID | NAME | DRIVER | SCOPE |
---|---|---|---|
cb092010df13 | bridge | bridge | local |
58c907ade07a | host | host | local |
6663b471b49f | none | null | local |
(一)None网络
- 网络特性:从名称即可看出,none网络是一种“无网络”状态的网络。在该网络下的容器,除了自身的回环接口(lo,用于容器内部进程间通信)外,没有其他任何网卡设备,无法与外部网络(包括其他容器和Docker主机以外的网络)进行通信。
- 创建与验证示例
-
首先,拉取busybox镜像(一个轻量级的Linux工具镜像,常用于测试),执行命令:
[root@docker ~]# docker pull busybox
-
然后,创建一个使用none网络的容器,指定容器名为cygalaxy,并使用
--rm
参数(容器退出后自动删除),执行命令: -
[root@docker ~]# docker run --name ycy1 -it --rm --network=none busybox:latest
-
进入容器后,通过
ip a
命令查看网络接口,输出如下:
从结果可以清晰看到,容器内仅存在lo回环接口,无其他网卡。/ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
-
- 适用场景:none网络的核心特点是封闭与隔离,适用于对安全性要求极高且无需联网的应用场景。例如,某个容器的唯一功能是生成随机密码,将其部署在none网络中,可以有效避免密码在网络传输过程中被窃取,最大程度保障数据安全。
(二)Host网络
- 网络特性:使用host网络的容器会直接共享Docker主机的网络栈,这意味着容器的网络配置(如IP地址、端口、路由表等)与Docker主机完全一致。容器可以直接使用Docker主机的网络资源与外部通信,无需进行额外的网络地址转换(NAT)。
- 创建与验证示例
-
执行命令创建使用host网络的容器:
-
[root@docker ~]# docker run --name ycy2 -it --rm --network=host busybox:latest
-
进入容器后,执行
ip a
命令查看网络接口,输出如下(示例):
可以看到,容器内显示的网卡信息(如ens33)和IP地址(如172.25.0.100/16)与Docker主机完全相同,证明容器共享了主机的网络栈。/ # ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000 link/ether 00:0c:29:f0:b0:2c brd ff:ff:ff:ff:ff:ff inet 192.168.100.40/24 brd 192.168.100.255 scope global noprefixroute ens33 valid_lft forever preferred_lft forever inet6 fe80::a1ca:afec:cf93:cb71/64 scope link noprefixroute valid_lft forever preferred_lft forever
-
- 端口冲突示例:使用host网络时,容器的端口会直接占用Docker主机的对应端口,若Docker主机上已有应用使用该端口,则会产生端口冲突。
- 例如,使用httpd镜像(Apache Web服务器镜像)创建一个使用host网络的容器,执行命令:
[root@docker ~]# docker run --name httpd -itd --network=host httpd
- 执行后,通过
ss -tpln | grep 80
命令查看80端口的占用情况,输出如下(示例):
若此时Docker主机上已有其他应用(如Nginx)占用80端口,则创建httpd容器会失败,提示端口已被占用。[root@docker ~]# ss -tpln | grep 80 LISTEN 0 128 *:80 *:* users:(("httpd",pid=10632,fd=4)) LISTEN 0 128 :::80 :::* users:(("httpd",pid=10632,fd=4))
- 例如,使用httpd镜像(Apache Web服务器镜像)创建一个使用host网络的容器,执行命令:
- 优缺点与适用场景
- 优点:由于容器直接使用主机网络栈,无需进行网络地址转换等额外操作,网络传输效率极高,适合对网络性能要求苛刻的应用。
- 缺点:牺牲了网络的灵活性,容器与主机共享端口资源,容易出现端口冲突;同时,容器的网络隔离性较差,容器内的网络操作可能会影响到主机。
- 适用场景:对网络传输速度要求极高,且能明确避免端口冲突的场景,例如高性能的数据库服务(需确保数据库端口在主机上唯一占用)。
(三)Bridge网络
Bridge网络是Docker默认的网络类型,Docker安装时会自动创建一个名为docker0
的Linux网桥(Bridge)。若创建容器时未通过--network
参数指定网络类型,容器会默认挂载到docker0
网桥上。
1. 默认Bridge网络(docker0)
-
初始状态查看:首先安装网桥管理工具
bridge-utils
(用于查看和管理Linux网桥),执行命令: -
[root@docker ~]# yum install bridge-utils
-
然后,通过
brctl show
命令查看docker0
网桥的初始状态,输出如下:
| bridge name | bridge id | STP enabled | interfaces |
| ----------- | ----------------- | ----------- | ---------- |
| docker0 | 8000.02425f2ee17b | no | (空) |
| virbr0 | 8000.5254008d8bec | yes | virbr0-nic |
可以看到,初始状态下docker0
网桥上未挂载任何网络接口(interfaces为空)。 -
容器创建后的网络变化:创建一个默认网络类型的容器(即使用bridge网络),执行命令:
[root@docker ~]# docker run --name ycy1 -it --rm busybox
-
此时,打开另一个终端,再次执行
brctl show
命令,会发现docker0
网桥上新增了一个网络接口(如veth98c678e),该接口就是新创建容器的虚拟网卡对应的一端。 -
进入容器,执行
ip a
命令查看容器内的网络接口,输出如下(示例):
/ # ip a
6: eth0@if7: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
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
容器内的eth0@if7
接口与docker0
上的veth98c678e
接口是一对veth pair(虚拟以太网对)。veth pair是一种特殊的网络设备,成对出现,可看作是由一根虚拟网线连接的两块网卡,其中一块网卡(eth0@if7
)位于容器内部,作为容器的网卡;另一块网卡(veth98c678e
)挂载在docker0
网桥上,从而实现容器与docker0
网桥的连接,使容器能够通过docker0
与其他容器或外部网络通信。
- Bridge网络配置信息:通过
docker network inspect bridge
命令可以查看默认bridge网络(docker0)的详细配置信息,其中与IP分配相关的配置如下:
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
可以看到,默认bridge网络的子网(Subnet)为172.17.0.0/16
,网关(Gateway)为172.17.0.1
(即docker0
网桥的IP地址)。当容器创建时,Docker会自动从该子网中分配一个未被占用的IP地址给容器,16位的子网掩码(对应65534个可用IP)确保了有足够多的IP地址供大量容器使用。
2. 自定义Bridge网络
除了Docker默认创建的bridge网络,我们还可以通过docker network create
命令,使用bridge驱动创建自定义的bridge网络,以满足不同场景下的网络需求(如自定义子网、网关,实现更灵活的网络隔离与通信控制)。
-
创建自定义Bridge网络示例:创建一个名为
ycy3
的自定义bridge网络,指定子网为172.19.0.0/16
,网关为172.19.0.1
,执行命令: -
[root@docker ~]# docker network create --driver bridge --subnet 172.19.0.0/16 --gateway 172.19.0.1 ycy3
-
执行
docker network ls
命令查看网络列表,会看到新增的ycy3
网络,输出如下(示例):
| NETWORK ID | NAME | DRIVER | SCOPE |
| ------------ | ------ | ------ | ----- |
| 7db6a96072e6 | ycy3 | bridge | local |
| cb092010df13 | bridge | bridge | local |
| … | … | … | … | -
执行
ip a
命令查看自定义bridge网络对应的网桥接口,输出如下(示例):
[root@docker ~]# ip a
8: br-7db6a96072e6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:af:17:3b:7b brd ff:ff:ff:ff:ff:ff
inet 172.19.0.1/16 brd 172.19.255.255 scope global br-7db6a96072e6
valid_lft forever preferred_lft forever
其中,br-7db6a96072e6
是ycy3
网络对应的网桥接口,其IP地址即为我们指定的网关172.19.0.1
。
-
创建容器并指定自定义Bridge网络:创建容器时,可通过
--network
参数指定使用自定义的bridge网络,还可通过--ip
参数为容器手动指定子网内的IP地址(若不指定,Docker会自动分配)。-
示例:创建一个名为
galaxycy
的容器,使用ycy3
网络,并指定IP为172.19.0.100
,执行命令: -
[root@docker ~]# docker run --name galaxycy -it --rm --network=ycy3 --ip 172.19.0.100 busybox
-
进入容器后,执行
ip a
命令查看IP配置,输出如下(示例):
/ # ip a 9: eth0@if10: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:13:00:64 brd ff:ff:ff:ff:ff:ff inet 172.19.0.100/16 brd 172.19.255.255 scope global eth0 valid_lft forever preferred_lft forever
可以看到,容器的IP地址已成功设置为
172.19.0.100
,符合我们的指定。 -
-
跨网络容器通信配置:默认情况下,不同网络中的容器无法直接通信。例如,使用默认bridge网络的容器
a1
和使用自定义ycy3
网络的容器a2
,二者无法直接互通。若要实现跨网络容器通信,可通过docker network connect
命令为容器添加额外的网络(即一个容器可同时属于多个网络)。-
步骤1:创建使用默认bridge网络的容器
a1
,执行命令: -
[root@docker ~]# docker run --name a1 -it --rm busybox
-
进入
a1
容器,执行ip a
查看IP,输出如下(示例):
/ # ip a 13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 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
-
步骤2:创建使用
ycy3
网络的容器a2
(后台运行),执行命令: -
[root@docker ~]# docker run --name a2 -itd --network=ycy3 --ip 172.19.0.100 busybox
-
步骤3:为
a2
容器添加默认bridge网络,执行命令: -
[root@docker ~]# docker network connect bridge a2
-
步骤4:通过
docker exec -it a2 sh
命令进入a2
容器,执行ip a
查看网络接口,输出如下(示例):
/ # ip a 15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:13:00:64 brd ff:ff:ff:ff:ff:ff inet 172.19.0.100/16 brd 172.19.255.255 scope global eth0 valid_lft forever preferred_lft forever 17: eth1@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff inet 172.17.0.3/16 brd 172.17.255.255 scope global eth1 valid_lft forever preferred_lft forever / # ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.269 ms 64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.078 ms 64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.093 ms
可以看到,
a2
容器现在拥有两个网卡(eth0
和eth1
),分别对应ycy3
网络(IP:172.19.0.100)和默认bridge网络(IP:172.17.0.3)。此时,a2
可以与a1
(IP:172.17.0.2)通过默认bridge网络直接通信,同时也能与ycy3
网络中的其他容器通信。 -
三、Docker容器之间的访问方式
容器之间的访问需要遵循一个核心原则:只有在同一个Docker网络中的容器才能够互相通讯。在此基础上,容器间访问主要有以下三种方式,且不同方式有其特定的适用场景和限制。
(一)基于IP地址进行访问
这是最基础的容器间访问方式,适用于已知目标容器IP地址的场景。只要两个容器处于同一个网络,就可以通过目标容器的IP地址进行通信(如ping测试、端口访问等)。
-
操作示例
-
步骤1:创建使用
ycy3
网络的容器mycy_1
,执行命令: -
[root@docker ~]# docker run --name mycy_1 -it --rm --network=ycy3 busybox
-
进入
mycy_1
容器,执行ip a
查看其IP地址,输出如下(示例):
/ # ip a 19: eth0@if20: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue link/ether 02:42:ac:13:00:02 brd ff:ff:ff:ff:ff:ff inet 172.19.0.2/16 brd 172.19.255.255 scope global eth0 valid_lft forever preferred_lft forever
可知
mycy_1
的IP为172.19.0.2
。-
步骤2:打开另一个终端,创建同样使用
ycy3
网络的容器mycy_2
,执行命令:[root@docker ~]# docker run --name mycy_2 -it --rm --network=ycy3 busybox
-
进入
mycy_2
容器,执行ping 172.19.0.2
命令测试与mycy_1
的通信,输出如下(示例):
/ # ping 172.19.0.2 PING 172.19.0.2 (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.060 ms 64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.062 ms 64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.058 ms
从输出可以看出,
mycy_2
能够成功ping通mycy_1
,证明基于IP地址的容器间访问方式有效。 -
-
优缺点
- 优点:实现简单,无需额外配置,只要知道目标容器IP且处于同一网络即可通信。
- 缺点:灵活性差。容器重启后,IP地址可能会发生变化(除非手动指定固定IP),若应用依赖固定IP访问其他容器,会导致通信中断;在大规模容器部署场景下,管理和维护大量容器的IP地址难度极大。
(二)基于容器名进行访问
为解决基于IP地址访问的灵活性问题,Docker从1.10版本开始,在docker daemon
(Docker守护进程)中实现了一个内嵌的DNS服务器。该DNS服务器会自动将容器名与容器的IP地址进行绑定,使得同一网络中的容器可以直接通过“容器名”进行通信,无需记忆或管理IP地址。
-
核心限制:只有在自定义的bridge网络中,容器才支持基于容器名的访问方式;使用默认bridge网络(docker0)的容器无法通过容器名互相访问。这是因为默认bridge网络未启用Docker内嵌的DNS解析功能,而自定义bridge网络默认启用了该功能。
-
操作示例
-
步骤1:创建使用自定义
ycy3
网络的容器cy1
(后台运行),执行命令:[root@docker ~]# docker run --name cy1 -itd --network=ycy3 busybox
-
步骤2:创建同样使用
ycy3
网络的容器cy2
,执行命令:[root@docker ~]# docker run --name cy2 -it --network=ycy3 busybox
-
进入
cy2
容器,执行ping cy1
命令,通过容器名cy1
访问目标容器,输出如下(示例):
/ # ping cy1 PING cy1 (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.046 ms 64 bytes from 172.19.0.2: seq=1 ttl=64 time=0.045 ms 64 bytes from 172.19.0.2: seq=2 ttl=64 time=0.051 ms
可以看到,
cy2
成功ping通了cy1
,证明基于容器名的访问方式有效。 -
-
DNS解析原理:当容器启动时,Docker daemon会将容器的名称(通过
--name
参数指定)和其分配到的IP地址关联起来,并将该映射关系写入内嵌的DNS服务器中。当同一网络中的其他容器通过容器名发起通信请求时,容器会先向Docker内嵌的DNS服务器发送域名解析请求,获取目标容器的IP地址,再基于IP地址进行通信。当容器停止或被删除时,Docker daemon会自动从DNS服务器中删除该容器对应的名称-IP映射关系,避免解析错误。 -
优缺点
- 优点:灵活性高,容器名通常是固定的(如应用名称),即使容器重启导致IP变化,其他容器仍可通过容器名正常访问;简化了大规模容器部署场景下的网络配置与管理。
- 缺点:依赖Docker内嵌的DNS服务,仅支持自定义bridge网络,无法在none网络、host网络或默认bridge网络中使用;若DNS服务出现故障,会导致容器间基于名称的通信中断。
(三)多个容器共享同一个网络协议栈(Joined容器)
Joined容器(也称为“联合容器”)是一种特殊的容器间通信方式,它允许两个或多个容器共享同一个网络栈(包括网卡、IP地址、端口、路由表等网络配置)。由于共享网络栈,这些容器之间可以通过回环地址(127.0.0.1)直接通信,无需经过外部网络转发,通信效率极高。
- 操作示例
-
步骤1:创建使用
ycy3
网络的容器cy3
(后台运行),执行命令:[root@docker ~]# docker run --name ycy3 -itd --network ycy3 busybox
-
步骤2:创建容器
cy4
,并指定其共享cy3
的网络栈,执行命令:[root@docker ~]# docker run --name ycy4 -it --rm --network=container:cy3 busybox
-
其中,--network=container:cy3
参数表示cy4
容器使用cy3
容器的网络栈。
- 进入`cy4`容器,执行`ping cy3`(或直接ping`cy3`的IP)测试通信,输出如下(示例):
```bash
/ # ping cy3
PING cy3 (172.19.0.3): 56 data bytes
64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.201 ms
64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.039 ms
64 bytes from 172.19.0.3: seq=2 ttl=64 time=0.036 ms
```
同时,由于共享网络栈,`ycy4`可以通过`127.0.0.1`访问`cy3`中运行的服务(例如,若`ycy3`中运行了一个监听`127.0.0.1:8080`的Web服务,`cy4`可直接通过`curl 127.0.0.1:8080`访问该服务)。
-
核心注意事项:端口冲突风险。由于多个容器共享同一个网络栈,它们的IP地址和端口资源是完全共享的。若不同容器中的应用绑定了相同的端口(如两个容器都启动了监听80端口的Web服务),则后启动的容器会因端口被占用而启动失败。因此,在使用Joined容器时,必须确保各容器内应用使用的端口不重复。
-
适用场景:适用于需要紧密耦合、高频通信的应用组件。例如,一个容器运行Web应用,另一个容器运行日志收集组件,日志组件需要实时读取Web应用的本地日志文件并发送到日志服务器。此时,将两个容器配置为Joined容器,日志组件可通过
127.0.0.1
直接访问Web应用的相关接口或文件,通信效率高且配置简单。
四、容器与外部网络的交互
除了容器之间的通信,容器与外部网络(如互联网、Docker主机所在的局域网)的交互也是Docker网络的重要组成部分,主要包括“容器访问外部网络”和“外部网络访问容器”两种场景。
(一)容器访问外部网络
Docker通过网络地址转换(NAT) 技术实现容器对外部网络的访问。当容器需要与外部网络(如访问百度官网)通信时,Docker会将容器的私有IP地址转换为Docker主机的公网(或局域网)IP地址,从而实现数据包的转发。
-
通信流程(以容器ping百度为例)
- 步骤1:容器
int_1
(假设IP为172.17.0.3
)发起ping请求,目标地址为www.baidu.com
,此时数据包的源地址为172.17.0.3
,目标地址为www.baidu.com
的IP(如180.101.49.11
)。 - 步骤2:数据包通过容器的虚拟网卡(如
eth0
)发送到docker0
网桥,docker0
网桥检测到目标地址为外部网络地址,将数据包转发给Docker主机的网络接口(如ens36
,假设其IP为192.168.31.106
)。 - 步骤3:Docker主机的NAT服务对数据包进行地址转换,将源地址从容器的私有IP(
172.17.0.3
)替换为Docker主机的IP(192.168.31.106
),同时记录该NAT映射关系(以便后续接收响应数据包时反向转换)。 - 步骤4:转换后的数据包从Docker主机的
ens36
接口发送出去,经过路由器等网络设备转发,最终到达www.baidu.com
的服务器。 - 步骤5:
www.baidu.com
服务器接收到ping请求后,返回响应数据包,目标地址为Docker主机的IP(192.168.31.106
)。 - 步骤6:响应数据包到达Docker主机后,NAT服务根据之前记录的映射关系,将目标地址从
192.168.31.106
反向转换为容器int_1
的IP(172.17.0.3
),并通过docker0
网桥转发给容器int_1
。 - 步骤7:容器
int_1
接收到响应数据包,完成一次ping通信。
- 步骤1:容器
-
关键技术:NAT(网络地址转换)是容器访问外部网络的核心技术。Docker默认启用了NAT功能,无需用户手动配置,即可实现容器与外部网络的通信。这种方式的优点是容器使用私有IP地址,无需占用公网IP资源,同时也提高了容器网络的安全性(外部网络无法直接访问容器的私有IP)。
(二)外部访问容器
默认情况下,外部网络(如Docker主机所在局域网中的其他电脑)无法直接访问容器,因为容器使用的是私有IP地址,且仅在Docker主机内部可见。要实现外部访问容器,主要有两种方法:使用host网络和端口映射。
1. 使用host网络
如前文所述,使用host网络的容器会共享Docker主机的网络栈,容器的IP地址和端口与Docker主机完全一致。因此,外部网络可以直接通过访问Docker主机的IP地址和容器使用的端口,实现对容器的访问。
-
示例:若Docker主机的IP为
192.168.31.106
,使用host网络的容器httpd
(运行Apache服务,监听80端口),则外部电脑(如IP为192.168.31.107
)可直接在浏览器中输入http://192.168.31.106:80
,访问容器httpd
提供的Web服务。 -
优缺点
- 优点:实现简单,无需额外配置端口映射;访问速度快,无地址转换开销。
- 缺点:端口冲突风险高,容器占用的端口会与Docker主机上的其他应用端口冲突;容器网络隔离性差,外部访问容器的同时也可能影响Docker主机的网络安全。
2. 端口映射(常用方式)
端口映射是Docker中最常用的外部访问容器的方式。它通过-p
参数(或-P
参数,随机映射端口)将容器内部对外提供服务的端口,映射到Docker主机的某个端口上。外部网络通过访问Docker主机的IP地址和映射后的端口,即可间接访问容器内部的服务。
-
操作示例(以httpd容器为例)
- 步骤1:创建httpd容器,将容器的80端口(Apache服务默认端口)映射到Docker主机的80端口,执行命令:
[root@docker ~]# docker run --name web1 -it -d -p 80:80 httpd
其中,-p 80:80
参数的格式为“主机端口:容器端口”,表示将Docker主机的80端口与容器的80端口进行映射。 - 步骤2:在Docker主机上测试访问,执行
curl http://127.0.0.1:80
命令,输出如下(示例):
<html><body><h1>It works!</h1></body></html>
该输出是Apache服务的默认首页内容,证明容器的Web服务已正常启动,且端口映射生效。
- 步骤1:创建httpd容器,将容器的80端口(Apache服务默认端口)映射到Docker主机的80端口,执行命令:
-
步骤3:外部网络访问。假设Docker主机的IP为
192.168.31.106
,外部电脑(如192.168.31.107
)可在浏览器中输入http://192.168.31.106:80
,即可访问容器web1
提供的Web服务,看到“It works!
”的页面。 -
端口映射的灵活性:端口映射支持多种配置方式,以满足不同需求:
- 映射到主机的指定端口:
-p 主机端口:容器端口
(如-p 8080:80
,将容器80端口映射到主机8080端口)。 - 绑定到主机的指定IP地址:
-p 主机IP:主机端口:容器端口
(如-p 192.168.31.106:8080:80
,仅允许通过主机的192.168.31.106
IP访问映射的8080端口)。 - 映射UDP端口:
-p 主机端口:容器端口/udp
(如-p 53:53/udp
,映射UDP协议的53端口,用于DNS服务)。 - 随机映射端口:
-P
(大写P),Docker会自动从主机的未占用端口中随机选择一个端口映射到容器的暴露端口(容器镜像中通过EXPOSE
指令声明的端口)。
- 映射到主机的指定端口:
-
优缺点
- 优点:灵活性高,可自由选择映射的主机端口,避免端口冲突;网络隔离性好,外部仅能访问映射的端口,容器的其他端口不会暴露给外部网络;支持多种映射配置,满足不同场景需求。
- 缺点:存在一定的网络性能开销,因为数据包需要经过端口映射的转发处理;若容器数量多,需要管理大量的端口映射关系,可能增加配置复杂度。
五、总结
- None网络:封闭隔离的网络,容器仅含lo回环接口,无法与外部通信,适用于高安全性、无需联网的场景(如生成随机密码的容器)。
- Host网络:容器共享Docker主机网络栈,网络性能最优,但存在端口冲突风险且隔离性差,适用于对网络性能要求极高的场景。
- Bridge网络:
- 默认bridge网络(docker0):容器默认使用,支持IP访问,但不支持容器名访问,适用于简单的测试场景。
- 自定义bridge网络:支持IP访问和容器名访问(依赖Docker内嵌DNS),可自定义子网和网关,支持跨网络容器通信配置,是生产环境中最常用的网络类型。
- 容器间访问核心规则:只有同一网络中的容器可互相通信;默认bridge网络不支持容器名访问,自定义bridge网络支持;Joined容器通过共享网络栈实现高效通信,但需避免端口冲突。
- 容器与外部交互:容器通过NAT访问外部网络;外部通过host网络或端口映射访问容器,其中端口映射因灵活性和安全性优势,成为主流方式。