Skip to content
60.Docker»20.网络模式»LV015-container模式.md

LV015-container模式

一、Container 模式拓扑

该模式 ≈bridge+host 的混合模式,指定一个容器以 bridge 方式启动,后面容器启动时指定网络模式为 container,它们自动共享第一个容器的网络资源。此时这两个容器共同使用同一网卡、主机名、IP 地址,容器间通讯可直接通过本地回环 lo 接口通讯。但这两个容器在其他的资源上,如文件系统、进程列表等还是隔离的。

img

二、有什么特点

(1)新创建的容器,仅同前面已存在的容器,共享网络空间,不与宿主机共享网络。

(2)新创建的容器,不会有自己的虚拟网卡和 IP,后面新创建容器的网络资源用的是上一个容器的。

(3)新创建的容器,仅仅是网络和第一个容器共享,其他资源彼此还都是相互隔离的。

弊端:第一个指定容器服务一旦停掉,后续的容器也没有办法继续运行

三、Container 模式示例

首先重开一个 CNB 开发环境,或者删掉之前运行的容器和镜像。

shell
docker ps -a  #列出所有容器列表
docker rm -f $(docker ps -qa)  #强制移除所有容器
docker ps -a

1. 未启动容器

1.1 宿主机网卡信息

shell
ifconfig

【例】

shell
  /workspace git:(main) ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:60:20:15:42  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.26.249.2  netmask 255.255.255.0  broadcast 172.26.249.255
        ether 02:42:ac:1a:f9:02  txqueuelen 0  (Ethernet)
        RX packets 1656  bytes 557438 (544.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1566  bytes 5434427 (5.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 66  bytes 5300 (5.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 66  bytes 5300 (5.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

此时,只有物理网卡 eth0 和 docker0 虚拟网卡,别无其他网卡。

1.2 宿主机 80 端口

先用命令 ss -lntup 或者 netstat -nalpt 验证一下,是否有未知程序占用 80 端口:

shell
docker ps -a   # 实验前,查看是否有启动的容器,如果有暂时先停掉,特别是 nginx 容器
netstat -nalpt # 实验前,先查看宿主机的(80)端口占用情况

对于这种模式可能不看这个信息,不过这里也记录一下吧。

【例】

shell
  /workspace git:(main) netstat -nalpt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:36000           0.0.0.0:*               LISTEN      87/sshd: /usr/sbin/ 
tcp        0      0 127.0.0.11:45371        0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:8686            0.0.0.0:*               LISTEN      72/node             
tcp        0      0 172.26.249.2:8686       172.26.249.1:58336      ESTABLISHED 72/node             
tcp        0      0 172.26.249.2:8686       172.26.249.1:58352      ESTABLISHED 231/node

会发现这里并没有任何服务占用 80 端口。

2. 启动容器

2.1 bridge 模式启动 nginx_Num1 容器

  • docker run 以 bridge 模式,启动第一个 nginx 容器 nginx_Num1
shell
docker images  #查看镜像列表
docker run -d --name nginx_Num1 nginx:alpine  #以bridge 桥接模式启动第一个 nginx

目的,便于对比,第二个容器以 container 网络模式启动后,网卡的变化。预期结果,其实并没有变化,后面启动的容器,都会使用第一个指定的以桥接方式启动的容器。

【例】

shell
  /workspace git:(main) docker run -d --name nginx_Num1 nginx:alpine
Unable to find image 'nginx:alpine' locally
alpine: Pulling from library/nginx
2d35ebdb57d9: Pull complete 
8f6a6833e95d: Pull complete 
194fa24e147d: Pull complete 
3eaba6cd10a3: Pull complete 
df413d6ebdc8: Pull complete 
d9a55dab5954: Pull complete 
ff8a36d5502a: Pull complete 
bdabb0d44271: Pull complete 
Digest: sha256:b3c656d55d7ad751196f21b7fd2e8d4da9cb430e32f646adcf92441b72f82b14
Status: Downloaded newer image for nginx:alpine
2f079b1b3917a4342f4cc04f8fef76d53c14bfbb3e39618d8a1d8db71d5081ee

2.2 查看宿主机端口

shell
netstat -nalpt # 查看宿主机的端口占用情况(主要看 80 端口)

【例】

shell
  /workspace git:(main) netstat -nalpt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:36000           0.0.0.0:*               LISTEN      87/sshd: /usr/sbin/ 
tcp        0      0 127.0.0.11:45371        0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:8686            0.0.0.0:*               LISTEN      72/node             
tcp        0      0 172.26.249.2:8686       172.26.249.1:58336      ESTABLISHED 72/node             
tcp        0      0 172.26.249.2:8686       172.26.249.1:58352      ESTABLISHED 231/node

2.3 查看宿主机网卡信息

shell
ifconfig

【例】

shell
  /workspace git:(main) ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        #...

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.26.249.2  netmask 255.255.255.0  broadcast 172.26.249.255
        #...

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        #...

vetha69edf2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::e07a:3eff:febf:56c  prefixlen 64  scopeid 0x20<link>
        ether e2:7a:3e:bf:05:6c  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14  bytes 1252 (1.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

可以发现,桥接模式下的容器,会自动创建以 veth 开头的虚拟网卡 。

2.4 查看 nginx_Num1 容器网络信息

shell
docker ps         # 查看正在运行的容器
docker inspect container_id # 根据容器 id 的首字母也可以查看容器详细信息

【例】

image-20251102001159800

第一个以桥接方式启动的容器的网络信息是全套的,ip 端口 网关,都有。

2.5 container 模式启动 tomcat 容器

shell
docker ps -a  # 查看容器列表(主要是查看刚才的 nginx_启动了没有)
docker run -d --name tomcat_Second  --net=container:nginx_Num1 tomcat:8.5.46-jdk8-openjdk # 以 container 模式启动第二个容器,注意,该模式不能使用-p

--net = container 后面直接跟冒号,冒号后面是它所依靠的以桥接方式启动的指定容器,即为:--net = container : nginx_Num1 , 其中 nginx_Num1 是上一步以 bridge 方式启动的第一个指定的容器。

注意:container 模式,docker run 的时候,不能使用-p,因为-p 是手动指定端口,而 container 模式的 ip 和端口是不受 container 模式的容器自身控制,它的 IP 和端口,相当于完全委托给第一个以桥接方式启动的容器了。

如果不小心带了-p 8080:8080 这个参数,你将看到这个错误:

shell
docker: Error response from daemon: conflicting options: port publishing and the container type network mode.

【例】

shell
  /workspace git:(main) docker run -d --name tomcat_Second  --net=container:nginx_Num1 tomcat:8.5.46-jdk8-openjdk
Unable to find image 'tomcat:8.5.46-jdk8-openjdk' locally
8.5.46-jdk8-openjdk: Pulling from library/tomcat
092586df9206: Pull complete 
ef599477fae0: Pull complete 
4530c6472b5d: Pull complete 
d34d61487075: Pull complete 
272f46008219: Pull complete 
12ff6ccfe7a6: Pull complete 
f26b99e1adb1: Pull complete 
21bec9c8ea28: Pull complete 
b8a32f28e27c: Pull complete 
94fdd0ba0430: Pull complete 
Digest: sha256:bb4ceffaf5aa2eba6c3ee0db46d863c8b23b263cb547dec0942e757598fd0c24
Status: Downloaded newer image for tomcat:8.5.46-jdk8-openjdk
f7cb8cb3a2a0054465ecc721cea1b6d60cf589e3032364893574712bf1e2c122

2.6 再次查看宿主机网卡信息

shell
ifconfig

【例】

shell
  /workspace git:(main) ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        #...

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.26.249.2  netmask 255.255.255.0  broadcast 172.26.249.255
        #...

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        #...

vetha69edf2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::e07a:3eff:febf:56c  prefixlen 64  scopeid 0x20<link>
        ether e2:7a:3e:bf:05:6c  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 18  bytes 1532 (1.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

发现并没有因为又启动一个容器而增加虚拟网卡。

2.7 查看 tomcat_Second 容器网络信息

shell
docker ps         # 查看正在运行的容器
docker inspect container_id # 根据容器 id 的首字母也可以查看容器详细信息

【例】

image-20251102001952104

发现,第二个以 container 模式启动容器的网络信息,IP、Mac 地址、网关、端口都是空的

2.8 tomcat_Second 容器能联网吗

我们通过以下命令进入 tomcat_Second 容器:

shell
docker ps
docker exec -it container_id /bin/sh
ping www.baidu.com

【例】

shell
  /workspace git:(main) docker ps                  
CONTAINER ID   IMAGE                        COMMAND                  CREATED          STATUS          PORTS     NAMES
f7cb8cb3a2a0   tomcat:8.5.46-jdk8-openjdk   "catalina.sh run"        9 minutes ago    Up 9 minutes              tomcat_Second
2f079b1b3917   nginx:alpine                 "/docker-entrypoint.…"   17 minutes ago   Up 17 minutes   80/tcp    nginx_Num1
  /workspace git:(main) docker exec f7cb8cb3a2a0 /bin/sh
  /workspace git:(main) docker exec -it f7cb8cb3a2a0 /bin/sh
# 
# ping www.baidu.com
PING www.a.shifen.com (183.2.172.17) 56(84) bytes of data.
64 bytes from 183.2.172.17 (183.2.172.17): icmp_seq=1 ttl=48 time=5.14 ms
64 bytes from 183.2.172.17 (183.2.172.17): icmp_seq=2 ttl=48 time=5.20 ms
^C
--- www.a.shifen.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 5.141/5.172/5.203/0.031 ms
#

发现是可以联网的。

2.9 访问 nginx_Num1 容器 nginx 服务

我们在宿主机访问一下 nginx_Num1 容器 nginx 服务:

shell
curl 172.17.0.2  #这个地址就是第一个以 bridger 方式启动的 nginx 的 Ip, 它的默认端口是 80

【例】

shell
  /workspace git:(main) curl 172.17.0.2
#...
<h1>Welcome to nginx!</h1>
#...

发现,是可以正常访问的。

2.10 非宿主机其他主机访问

在非宿主机的其他局域网主机访问虚拟内部容器是无法访问的:

image-20251102002728769

这里照搬一张图,因为我是在 CNB 云原生开发中验证,暂时还不知道怎么搞一个同网段的其他主机,这里就没有尝试了。

参考资料:

Docker:网络模式详解 - Gringer - 博客园

Docker 四种网络模式(Bridge,Host,Container,None) - wq9 - 博客园

Docker 学习:容器五种(3+2)网络模式 | bridge 模式 | host 模式 | none 模式 | container 模式 | 自定义网络模式详解-CSDN 博客

莫道桑榆晚 为霞尚满天.