Docker网络

一、Docker网络概念

1、网络驱动

Docker 网络子系统使用可插拔的驱动,默认情况下有多个驱动程序,并提供核心联网功能。

  1. bridge:桥接网络,这是默认的网络驱动程序(不指定驱动程序创建的容器默认是bridge驱动)。
  2. host:主机网络。消除容器和主机的网络隔离,直接使用主机的网络。
  3. overlay:覆盖网络。可以将多个Docker守护进程连接,实现跨主机容器通讯(swarm集群)。
  4. macvlan:将MAC地址分配给容器,使容器作为网络上的物理设备。不通过Docker主机网络栈进行路由,直接通过MAC地址路由到容器。
  5. none:表示关闭容器的所有网络连接。常与自定义网络驱动一起使用,不适用于swarm。
  6. 网络插件:可以通过Docker安装和使用第三方网络插件。

2、Docker 网络驱动选用原则

  1. bridge桥接网络:最适合用于同一个Docker主机上运行的多个容器之间需要通信的场景。(单主机)
  2. host主机网络:最适用于当网络栈不能与Docker主机隔离,而容器的其他方面需要被隔离的场景。(解除容器和主机隔离)
  3. overlay网络:适用于不同Docker主机上运行的容器需要通信的场景,或者多个应用程序通过Swarm集群服务一起工作的场景。(多主机、集群)
  4. macvlan网络:适用于从虚拟机迁移过来的场景,或者容器需要像网络上的物理机一样,拥有独立MAC地址的场景。(容器需要mac)
  5. 第三方网络插件适用于将Docker与专用网络栈进行集成的场景。(订制化)

3、容器的网络模式

docker内置了四种网络模式,也可以使用自定义网络。

(1)bridge模式

桥接网络分为默认桥接网络用户自定义桥接网络两种类型。

桥接网络用于同(单)主机运行的容器间通信。

实现原理:桥接网络使用软件网桥,让连接到同一桥接网络的容器可以通信,没连接该网桥的容器被隔离。

工作流程:Docker守护进程启动,会在主机上创建一个名为 docker0 的虚拟网桥,启动容器时如果没有特别指定,自动连接到这个虚拟网桥。

[root@localhost ~]# 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:b2:81:22:9d  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

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.100.111  netmask 255.255.255.0  broadcast 192.168.100.255
		
# 案例:默认桥接网络和用户自定义桥接网络
[root@huangqiushi ~]# docker network create --driver bridge hqs-net
c330cf15a47d29057a89a4313e5734348799bde32fba4dd71376382b049f1c86
[root@huangqiushi ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
73ab60681376   bridge    bridge    local
76d9e06a3606   host      host      local
c330cf15a47d   hqs-net   bridge    local
9f44873071f4   none      null      local

Docker 守护进程为每个启动的容器创建一个 VETH对设备(总是成对出现,组成数据通道)。

VETH对是直接连接的一对虚拟网络接口,一个接口设置为新创建容器的接口(位于容器的网络名称空间中);另一个接口连接到虚拟网桥docker0(位于Docker的网络名称空间中)。

(2)host模式

host模式的容器使用host驱动,直接连接Docker主机网络栈。实质:关闭 Docker 网络,让容器直接使用主机操作系统的网络。

host模式没有为容器创建一个隔离的网络环境,容器没有隔离的网络名称空间,也不会获得一个独立的网络名称空间,而是和Docker主机共用一个网络名称空间

容器和主机在同一个网络中,使用主机的物理网络接口,没有独立的IP地址,直接使用主机的IP地址和端口

由于主机名、地址都一样,因此同一主机上的容器要做好协调。各容器通过端口来进行区分。

(3)container模式

Docker中一种较为特别的网络模式,主要用于容器和容器直接频繁交流的情况。

Kubernetes 集群使用这种网络模式。

特点:

  1. 该模式指定新建的容器和现有的一个容器共享网络名称空间。
  2. 新创建的容器和一个现有的指定容器共享IP地址、端口范围,不创建自己的网络接口、IP地址。
  3. 两个容器间网络不隔离,进程可通过回环网络进行通信。
  4. 这两个容器和主机和其他容器存在网络隔离。

(4)none模式

none模式将容器放置在它自己的网络栈中,但是并不进行任何配置,实际上关闭了容器的网络功能

特性:none模式,容器有自己的网络名称空间,但未进行任何网络配置,未构建任何网络环境,容器内部只能使用回环网络接口(127.0.0.1)。

可用场景:

  1. 有些容器并不需要网络,例如只需要写入磁盘卷的批处理任务。
  2. 安全性要求高并且不需要联网的应用可以使用none模式。
  3. 要创建自定义网络

(5)用户自定义网络模式

管理员可以使用Docker网络驱动(bridge、overlay、macvlan)或第三方网络驱动插件创建一个自定义的网络,然后将多个容器连接到同一个自定义网络。

特点:

  1. 连接到用户自定义网络的容器,可以使用IP地址或名称相互通信。
  2. 可以根据需要创建任意数量的自定义网络。
  3. 可以在任何时间将容器连接到这些网络。
  4. 对运行中的容器,可连接、断开自定义网络,无须重启容器。

用户自定义桥接网络(自定义网络使用bridge网络驱动):单机环境常用。生产环境推荐使用。

生产环境不推荐使用默认桥接网络,推荐使用用户自定义桥接网络,原因在以下区别:

  1. 用户自定义桥接网络能提供容器化应用程序之间更好的隔离和互操作性。如果在默认桥接网络上运行应用栈,则Docker主机需要通过其他方式来限制对端口的访问。
  2. 用户自定义桥接网络提供容器之间自动DNS解析功能,可以通过名称或别名互相访问。而默认桥接网络上的容器只能通过IP地址互相访问。
  3. 容器可以在运行时与用户自定义网络连接和断开。要断开与默认桥接网络的连接,需要停止容器并使用不同的网络选项重新创建该容器。
  4. 每个用户可通过自定义网络创建一个可配置的网桥。而默认桥接网络会自动穿件一个名为docker0的虚拟网桥。
  5. 用户自定义网络中所连接容器不能共享环境变量,不过有更好的方式实现共享环境变量(docker卷挂载、compose文件定义、集群)。默认桥接网络中所连接的容器共享环境变量。

4、容器间的通信方案

容器间通信方案:

  1. bridge模式让同一个Docker网络上的所有容器在所有端口上都可以相互连接。
    • 默认桥接网络不支持基于名称的服务发现和用户指定的IP地址,所连接的容器只能通过IP地址互相访问,除非创建容器时使用--link选项建立容器连接。
    • 在用户自定义桥接网络中,容器之间可以通过名称或别名互相访问。
  2. host模式让所有容器都位于同一个主机网络空间中,并共用主机的IP地址栈,在该主机上的所有容器都可通过主机的网络接口相互通信。
  3. 容器通过端口映射对外部提供连接。
  4. container模式让容器共用一个IP网络,两个容器之间可通过回环网络接口相互通信。
  5. 容器之间使用--link选项建立传统的容器互联。
  6. 容器之间通过挂载主机目录来实现相互之间的数据通信。

5、传统容器连接

创建容器时使用--link选项可以在容器之间建立连接,这是Docker传统的容器互联解决方案。

特性:

  1. 这种连接方式用来将多个容器连接在一起,并在容器之间发送连接信息。
  2. 当容器被连接时,在源容器接收容器 之间建立一个安全通道,关于源容器的信息能够被发送到接收容器,让接收容器可以访问源容器所指定的数据。

为容器设置自定义名称的好处:

  • 表示特定用途的名称更易记忆,如将一个Web应用的容器命名为web。
  • 便于Docker通过该名称引用其他容器,弥补默认桥接网络不支持容器名称解析的不足
# 语法
[root@localhost ~]# docker create --help
Usage:  docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
Create a new container
Options:
  --link list                      Add link to another container       # 添加连接到另一个容器
# 格式
--link <源容器的名称或ID>
--link <源容器的名称或ID>:容器别名

# 案例
# 创建容器时,添加到第一个容器的连接,并配置别名alp
[root@localhost ~]# docker run -dti --name alpine2 --link alpine1:alp alpine ash
21c0ddd94cb4d7190701d003868caef7cd9f82aded0ae0c5a2e9e68ebb45a03f

6、容器访问外部网络

默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。

使用bridge模式(默认桥接网络)的容器通过NAT方式实现外部访问,具体通过iptables(Linux的包过滤防火墙)的源地址伪装操作实现。

iptables源地址伪装:容器所有到外部网络的连接,源地址都会被 NAT 装换成本地系统的 IP 地址(即docker0地址)。

查看主机的 NAT 规则:

[root@localhost ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 142 packets, 31842 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    1    52 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 140 packets, 31384 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 4 packets, 288 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT 4 packets, 288 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0             《————这一条规则将所有源地址在 172.17.0.0/16 网段,目标地址为其他网段(外部网络)的流量动态伪装为从系统网卡发出。
	                                                                                                MASQUERADE 相比传统 SNAT 的好处是它能动态从网卡获取地址。

Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0  

7、从外部网络访问容器

默认情况下,创建的容器不会将其任何端口对外发布,从容器外部无法访问容器内部。

从外部访问容器内的应用程序必须要有明确的授权,通过内部端口映射来实现。

实现:将容器的一个端口映射到 docker 主机上的一个端口,允许从外部网络通过该端口访问容器。这种端口映射也是一种NAT实现,即目标地址转换(Destination NAT DNAT)。

# 案例
[root@localhost dockerfile-test]# docker run --rm -d -p 8000:80 --name my-nginx centos-nginx-hqs:1.0

(1)-P发布容器所有暴露的端口

通过docker run命令创建容器时使用-P选项将容器中所有暴露的端口发布到Docker主机上随机的高端地址端口中。
要求容器中要发布的端口必须提前暴露出来。
有两种方式可以暴露端口:一种是在Dockerfile中使用EXPOSE指令定义,另一种是执行docker run命令创建容器时使用--expose选项指定。

# 1.创建容器使用-P选项发布httpd服务
[root@hqs ~]# docker pull httpd
[root@hqs ~]# docker run --rm -d --name websrv -P httpd
adc5a789b20c170b229d6aafa879fd2cad54eb363259be994e6d21841ecf08f5

# 2.使用docker port 查看容器的端口映射设置
[root@hqs ~]# docker port websrv
80/tcp -> 0.0.0.0:49153               《————左边是容器发布的端口80,右边是映射到主机上的IP地址和端口49153
80/tcp -> :::49153

# 3.使用curl命令访问服务测试
[root@hqs ~]# curl http://192.168.100.111:49153
<html><body><h1>It works!</h1></body></html>

(2)-p发布容器特定端口

通过 docker run 命令启动容器,可以使用 -p 选项将容器的一个或多个端口映射到主机上。

可以多次使用 -p 设置任意数量的端口映射。

选项格式 说明 示例
-p 主机端口:容器端口 映射主机上所有网络接口的地址 -p 8080:80
-p 主机IP地址:主机端口:容器端口 映射指定地址的指定端口 -p 192.168.10.10:80:5000
-p 主机IP地址::容器端口 映射指定地址的任一端口 -p 127.0.0.1::5010
-p 容器端口 自动分配主机端口 -p 5200
-p 以上各种格式/udp 发布UDP端口(默认为TCP端口) -p 8080:80/udp
-p 以上各种格式/tcp -p 以上各种格式/udp 同时发布TCP和UDP端口 -p 8080:80/tcp -p 8080:80/udp
# 案例1:映射主机上所有网络接口的地址
[root@hqs ~]# docker run -dti --name websrv -p 8000:80 httpd
edc35a9e8b6dded9abb82906e02258cba32c608bf7e3face09e9d3d4308a60fc
[root@hqs ~]# docker port websrv
80/tcp -> 0.0.0.0:8000
80/tcp -> :::8000
[root@hqs ~]# curl http://192.168.100.111:8000
<html><body><h1>It works!</h1></body></html>

# 案例2:映射指定地址的指定端口
[root@hqs ~]# docker run -dti --name websrv2 -p 192.168.100.111:8001:80 httpd
1d19b8a06483811bab9b5b5767cf8c38aabe911f3ed2df5250a1e155a7276e7e
[root@hqs ~]# docker port websrv2
80/tcp -> 192.168.100.111:8001
[root@hqs ~]# curl http://192.168.100.111:8001
<html><body><h1>It works!</h1></body></html>

# 案例3:映射指定地址的任一端口
[root@hqs ~]# docker stop websrv websrv2
websrv
websrv2
[root@hqs ~]# docker run -dti --name websrv3 -p 127.0.0.1::80 httpd
19057827c1c7477e860a2f6ebd6c1dd4c1f2fd4386c61a3c6aafcf39a317ea65
[root@hqs ~]# docker port websrv3
80/tcp -> 127.0.0.1:49153
[root@hqs ~]# curl http://127.0.0.1:49153
<html><body><h1>It works!</h1></body></html>

# 案例4:自动分配主机端口
[root@hqs ~]# docker run -dti --name websrv4 -p 80 httpd
3ccb4a496636eb774452c900acdd8f3ca0f4d5bf99c58618e266e6f83ae6c55b
[root@hqs ~]# docker stop websrv3
websrv3
[root@hqs ~]# docker port websrv4
80/tcp -> 0.0.0.0:49154
80/tcp -> :::49154
[root@hqs ~]# curl http://192.168.100.111:49154
<html><body><h1>It works!</h1></body></html>

# 案例5:发布UDP端口
[root@hqs ~]# docker run -dti --name websrv5 -p 8080:80/udp httpd
9ae61cbd4e67b606ee38ace205036c458edf6eecb67b908a87e9363ae63a8f55
[root@hqs ~]# docker port websrv5
80/udp -> 0.0.0.0:8080
80/udp -> :::8080

# 案例6:同时发布TCP和UDP端口
[root@hqs ~]# docker run -dti --name websrv6 -p 8080:80/tcp -p 8080:80/udp httpd
d13977a616392d890c6335ba4446d88eeb033e65c8fafb9379c0593e50dde861
[root@hqs ~]# docker port websrv6
80/tcp -> 0.0.0.0:8080
80/tcp -> :::8080
80/udp -> 0.0.0.0:8080
80/udp -> :::8080

8、容器的网络配置语法

使用 docker rundocker create 命令来设置容器的网络配置的语法。

(1)设置容器的网络连接

容器启动时,可以使用 --network 选项设置容器要连接的网络,即网络模式。

none:容器为none模式,容器不使用任何网络连接,能完全禁用网络连接。

bridge:容器为bridge模式,连接到默认桥接网络,也是默认设置。

host:容器为host模式,使用主机网络栈。

container:容器为container模式,容器使用某一个容器(通过id或name来标识)的网络栈。

网络名or网络id:容器连接自定义网络,可使用自定义网络的名称或id。

# 语法
[root@localhost ~]# docker run --help
Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
      --network network                Connect a container to a network        # 连接容器到网络中

# 案例
[root@hqs ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
9b3f5f5076b9   bridge    bridge    local
76d9e06a3606   host      host      local
9f44873071f4   none      null      local
[root@hqs ~]# docker run --network none -dit --name centos-test centos /bin/bash
24110a1ca4da0f6d7659d7d2e8a1f57a8d980031ab54ac4730a3b89e44679e46
[root@hqs ~]# docker inspect --format='{{json .HostConfig.NetworkMode}}'  24110a1ca4da 
"none"

(2)为容器添加网络作用域的别名

容器在网络作用域中允许有别名,别名在所在网络中可以直接访问。使用 --network-alias 选项指定容器在网络中的别名。

注意:网络作用域别名只支持用户自定义的网络。

# 语法
[root@localhost ~]# docker run --help
Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
      --network-alias list             Add network-scoped alias for the container   # 给容器添加网络作用域别名

# 失败案例一:
[root@hqs ~]# docker run -d -p 80:80 --name testweb --network host --network-alias websrv centos
docker: network-scoped aliases are only supported for user-defined networks.       # 网络作用域别名只支持用户自定义的网络
# 失败案例二:
[root@localhost ~]# docker run -tid -p 8081:80 --name testweb --network-alias websrv  centos 
# 再创建一个默认桥接网络的容器,并登录
[root@localhost ~]# docker exec -ti e53054da3bcd /bin/bash
[root@e53054da3bcd /]# ping websrv
ping: websrv: Name or service not known      《——————网络别名无法访问

# 成功案例
[root@hqs ~]# docker network create --driver bridge mynet
a7b402ee062eaf27c50fb303ae6e764f384cd7b2ebd0acf61fdeeba68bddb5f6
[root@hqs ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
9b3f5f5076b9   bridge    bridge    local
76d9e06a3606   host      host      local
a7b402ee062e   mynet     bridge    local
9f44873071f4   none      null      local
# 启动容器
[root@localhost ~]# docker run -tid -p 8082:80 --name test-web01 --network mynet --network-alias webtest centos   
[root@localhost ~]# docker run -tid -p 8083:80 --name test-web02 --network mynet --network-alias webtest02 centos 
# 查看网络模式
[root@huangqiushi ~]#  docker inspect --format='{{json .HostConfig.NetworkMode}}'  test-web01
"mynet"
# 查看自定义网络信息
[root@huangqiushi ~]#  docker inspect --format='{{json .NetworkSettings.Networks.mynet}}'  test-web01
{"IPAMConfig":null,"Links":null,"Aliases":["webtesthqs","99e3e91c8212"],"NetworkID":"f5d3fe3303c75faccc4ecbdb740d65865e2c05364608dc14602d110daa32bce6","EndpointID":"","Gateway":"","IPAddress":"","IPPrefixLen":0,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"","DriverOpts":null}
# 查看网络别名
[root@huangqiushi ~]#  docker inspect --format='{{json .NetworkSettings.Networks.mynet.Aliases}}'  test-web01
["webtesthqs","99e3e91c8212"]
# 查看端口映射
[root@huangqiushi ~]#  docker inspect --format='{{json .HostConfig.PortBindings}}'  test-web01
{"80/tcp":[{"HostIp":"","HostPort":"8082"}]}

# 两个容器互ping    《————网络别名可以互相访问
[root@localhost ~]# docker exec -ti test-web02 /bin/bash
[root@f390714cdfd2 /]# ping webtest
PING webtest (172.18.0.2) 56(84) bytes of data.
64 bytes from test-web01.mynet (172.18.0.2): icmp_seq=1 ttl=64 time=0.089 ms
64 bytes from test-web01.mynet (172.18.0.2): icmp_seq=2 ttl=64 time=0.102 ms
[root@localhost ~]# docker exec -ti test-web01 /bin/bash                                
[root@e65e3fb78f6f /]# ping webtest02
PING webtest02 (172.18.0.3) 56(84) bytes of data.
64 bytes from test-web02.mynet (172.18.0.3): icmp_seq=1 ttl=64 time=0.029 ms
64 bytes from test-web02.mynet (172.18.0.3): icmp_seq=2 ttl=64 time=0.061 ms

(3)设置容器的IP地址

使用--network 选项启动容器连接自定义网络时,可以使用 --ip--ip6选项明确指定分配给该网络容器的ip地址。

使用前面创建的mynet,创建新容器指定ip时报错:Error response from daemon: user specified IP address is supported only when connecting to networks with user configured subnets.

注意有两个前置使用条件:

  1. 只适用用户自定义网络;
  2. 用户自定义网络配置了子网。
# 语法
[root@localhost ~]# docker run --help
Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
      --ip string                      IPv4 address (e.g., 172.30.100.104)
      --ip6 string                     IPv6 address (e.g., 2001:db8::33)

# 案例:使用默认网络--ip配置地址不生效
[root@hqs ~]# docker run -dti --name test-ip --ip 172.17.1.100 centos 
04ffb3d192dd681f07ba53d828f515f6376376ae3dbc29b69c6f8fa5f06b6f17
[root@hqs ~]# docker inspect --format='{{json .NetworkSettings.IPAddress}}'  test-ip
"172.17.0.2"

# 案例
[root@hqs ~]# docker network create --driver bridge --subnet 10.10.0.0/24 --gateway 10.10.0.254 hqsnet2
bb6f77c8b7f0525d0563ae9e85ef4b8a829ac5fee5a4f666c0caff4fcbc1b67b
[root@hqs ~]# docker network inspect hqsnet2
[
    {
        "Name": "hqsnet2",
        "Id": "bb6f77c8b7f0525d0563ae9e85ef4b8a829ac5fee5a4f666c0caff4fcbc1b67b",
        "Created": "2022-04-15T03:26:05.242174757+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "10.10.0.0/24",
                    "Gateway": "10.10.0.254"
                }
            ]
        }
    }
]
[root@hqs ~]# docker run -dti --name test-ip02 --network hqsnet2 --ip 10.10.0.101 centos
1377b1fe89549cf87833f6188c3a6355c39cec86d6237e7141a958befb8a176a
[root@hqs ~]# docker inspect --format='{{json .NetworkSettings.Networks.hqsnet2.IPAddress}}'  test-ip02
"10.10.0.101"

(4)设置容器的网络接口MAC地址

默认情况下,容器mac地址是基于其IP地址生成。
可以通过 --mac-address 选项为容器指定一个MAC地址。

注意:手动指定mac地址,docker不会检查地址的唯一性。

手动生成MAC地址:

[root@localhost ~]# openssl rand -hex 6 | sed 's/../&:/g; s/.$//'
33:68:aa:ad:00:a3

[root@localhost ~]# openssl rand -hex 6 | sed 's/\(..\)/\1:/g; s/.$//'
e9:94:81:c6:ee:ca

配置容器mac地址:

# 语法
[root@localhost ~]# docker run --help
Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
      --mac-address string             Container MAC address (e.g., 92:d0:c6:0a:29:33)

# 案例1:(默认网络)使用宿主机mac
[root@hqs ~]# docker run -dti --name test-dns01 --mac-address 56:78:ab:bc:8c:1d  centos
f4e0babb3072cc2a1484e68b7fcbd733194a462660f5ee571072c6fb575f7683
[root@hqs ~]# docker inspect --format='{{json .Config.MacAddress}}' test-dns01
"56:78:ab:bc:8c:1d"

# 案例2:(自定义网络)使用宿主机mac
[root@hqs ~]# docker run -d -p 8080:80 --name testweb03 --network mynet --network-alias web03 --mac-address 12:34:56:78:9a:bc  centos
4bc34a65f48f46b95c021194dec216f640d8974f98c6c297dcc37c64f924436b
[root@hqs ~]# docker inspect --format='{{json .Config.MacAddress}}'  4bc34a65
"12:34:56:78:9a:bc"

# 案例3:使用非宿主机MAC
# 直接用自动生成的mac地址会报错:
[root@localhost ~]# docker run -tid --name test-dns02 --mac-address 33:68:aa:ad:00:a3 --network mynet  centos
b879124d471c0a92a893d78a710f68c7ba6aa2273cf774f38c0fb51534f79452
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running hook #0: error running hook: exit status 1, stdout: , stderr: time="2023-04-04T22:23:17+08:00" level=fatal msg="failed to add interface veth772efc3 to sandbox: error setting interface \"veth772efc3\" MAC to \"33:68:aa:ad:00:a3\": cannot assign requested address": unknown."

# 查看宿主机的自定义网络网桥mac地址
[root@localhost ~]# ifconfig
br-1d464e4efefe: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:a5:6a:53:eb  txqueuelen 0  (Ethernet)

# 根据宿主机mac地址编写设置mac
[root@localhost ~]# docker run -tid --name test-dns03 --mac-address  02:42:a6:14:23:03 --network mynet  centos 
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE                COMMAND                  CREATED          STATUS                        PORTS                                   NAMES
a51c28393d30   centos               "/bin/bash"              4 minutes ago    Up 4 minutes                                                          test-dns03
b879124d471c   centos               "/bin/bash"              12 minutes ago   Created                                                               test-dns02    《————这个无法启动

# 容器网卡详情查看
[root@localhost ~]# docker inspect --format='{{json .Config.MacAddress}}'  test-dns03   
"02:42:a6:14:23:03"
[root@localhost ~]# docker inspect --format='{{json .NetworkSettings.Networks.mynet.MacAddress}}'  test-dns03
"02:42:a6:14:23:03"

(5)设置容器的DNS配置和主机名

默认情况下,容器继承Docker守护进程的DNS配置,包括 /etc/hosts/etc/resolv.conf 配置文件。

可以使用以下选项配置DNS,覆盖默认配置。

# 语法
[root@localhost ~]# docker run --help
Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
      --dns list                       Set custom DNS servers            # 为容器设置DNS服务器的IP地址
	  可以使用多个--dns为容器指定多个DNS服务器。
	  容器连不上指定DNS服务器,会自动使用google的公共dns:8.8.8.8。
      --dns-option list                Set DNS options                   # 为容器设置表示DNS选项及值的键值对
	  
      --dns-search list                Set custom DNS search domains     # 为容器指定一个DNS搜索域
	  搜索非全称的主机名。
	  可以使用多个--dns-search的选项
  -h, --hostname string                Container host name               # 为容器指定自定义的主机名
  

# --dns案例
[root@hqs ~]# docker run -d -p 8081:80 --name testdns --network mynet --dns 202.103.24.68  centos
101cf268006a5780c9e69e147d302933aa91bace5922c5527d41f5dcec4a23f9
# 如果配置错误DNS,测试发现一开始会找不到地址,过一段时间后才能转换域名为ip
# 登录测试
[root@hqs ~]# docker exec -ti test-dns-opt02 /bin/bash
[root@c51e9e87b4e6 /]# ping www.baidu.com
PING www.wshifen.com (103.235.46.39) 56(84) bytes of data.
64 bytes from 103.235.46.39 (103.235.46.39): icmp_seq=4 ttl=127 time=293 ms
[root@hqs ~]# docker inspect --format='{{json .HostConfig.Dns}}'  101cf268
["202.103.24.68"]
# 登录容器查看配置文件       《《《————和想象中不一样,找到原因????
[root@localhost ~]# docker exec -ti testdns /bin/bash
[root@e6f003f0889e /]# cat /etc/resolv.conf 
nameserver 127.0.0.11
options ndots:0

# --dns-option案例
# 参照resolv.conf文件来确定选项
[root@localhost ~]# docker run --name test-dns-opt02 -dit --dns-option asdasd  centos   
5a6addb236356b3f5466873e4279506f8c6ee88b2b775f0aca2388bdf940e220
# 查看配置
[root@hqs ~]# docker inspect --format='{{json .HostConfig.DnsOptions}}'  test-dns-opt02
["asdasd"]
# 连接容器查看修改的内容
[root@localhost ~]# docker exec -ti test-dns-opt02 /bin/bash
[root@5a6addb23635 /]# cat /etc/resolv.conf 
nameserver 8.8.8.8
options asdasd

# --dns-search案例
[root@hecs-hqs-01 ~]# docker run -dti -p 8082:80 --name test_dns_search --network mynet --dns-search openstacklocal centos
b23a978d072acf45a90a093883c3494d0b3383c817ffe76708c9fd132df00358
[root@hecs-hqs-01 ~]# docker ps -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                    NAMES
b23a978d072a        centos                "/bin/bash"              5 seconds ago       Up 4 seconds        0.0.0.0:8082->80/tcp     test_dns_search
[root@hecs-hqs-01 ~]# docker inspect --format='{{json .HostConfig.DnsSearch}}'  test_dns_search
["openstacklocal"]
# 登录容器查看修改的内容
[root@localhost ~]# docker exec -ti test_dns_search /bin/bash
[root@31435d885b7b /]# cat /etc/resolv.conf 
search openstacklocal
nameserver 8.8.8.8

# --hostname案例
[root@hecs-hqs-01 ~]# docker run -dti -p 8083:80 --name test_hostname --network mynet --hostname hostname-test centos
5f49da1802ea461de7133beb4c8460a75a8cf687648ef1d135757b79f7e2c30b
[root@hecs-hqs-01 ~]# docker ps -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS              PORTS                    NAMES
5f49da1802ea        centos                "/bin/bash"              4 seconds ago        Up 3 seconds        0.0.0.0:8083->80/tcp     test_hostname
[root@hecs-hqs-01 ~]# docker inspect --format='{{json .Config.Hostname}}'  test_hostname 
"hostname-test"
# 登录容器查看修改内容
[root@localhost ~]# docker exec -ti test_hostname /bin/bash
[root@hostname-test /]# cat /etc/hosts 
127.0.0.1       localhost
...略
172.17.0.4      hostname-test

二、Docker网络管理命令

docker network 是Docker 网络本身的管理命令。

# 语法
[root@localhost ~]# 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                                     # 删除指定网络

1、查看网络列表

执行 docker network ls 命令,可查看当前网络列表。

网络作用域为local,则仅在docker主机范围内提供连接和网络服务。

# 语法
[root@localhost ~]# docker network ls --help
Usage:  docker network ls [OPTIONS]
List networks
Aliases:
  ls, list
Options:
  -f, --filter filter   Provide filter values (e.g. 'driver=bridge')     # 过滤
      --format string   Pretty-print networks using a Go template        # 格式化输出
      --no-trunc        Do not truncate the output                       # 不截断输出
  -q, --quiet           Only display network IDs                         # 只显示网络ID
  

# 案例
[root@localhost ~]# docker network ls 
网络ID       网络名称    网络驱动  作用域
NETWORK ID     NAME      DRIVER    SCOPE
989e0968a6fe   bridge    bridge    local
76d9e06a3606   host      host      local
9f44873071f4   none      null      local

# -q 只显示id
[root@localhost ~]# docker network ls -q
989e0968a6fe
76d9e06a3606
9f44873071f4

# --filter 根据条件筛选
[root@localhost ~]# docker network ls --filter driver=bridge
NETWORK ID     NAME      DRIVER    SCOPE
989e0968a6fe   bridge    bridge    local
[root@localhost ~]# docker network ls --filter name=host
NETWORK ID     NAME      DRIVER    SCOPE
1ab297d47d87   host      host      local
[root@localhost ~]# docker network ls --filter scope=local
NETWORK ID     NAME      DRIVER    SCOPE
08e3d1836794   bridge    bridge    local
1ab297d47d87   host      host      local
1d464e4efefe   mynet     bridge    local
65337a3625c6   none      null      local
[root@localhost ~]# docker network ls --filter id=08e3d1836794
NETWORK ID     NAME      DRIVER    SCOPE
08e3d1836794   bridge    bridge    local

# --format 格式化输出
[root@localhost ~]# docker network ls --format='{{.ID}}---{{.Name}}---{{.Driver}}---{{.Scope}}'
08e3d1836794---bridge---bridge---local
1ab297d47d87---host---host---local
1d464e4efefe---mynet---bridge---local
65337a3625c6---none---null---local

# --no-trunc 显示完整ID
[root@localhost ~]# docker network ls --no-trunc
NETWORK ID                                                         NAME      DRIVER    SCOPE
989e0968a6fe9b95dd76238e4707f40bc0cf288fd6b764acbd537954fd0e6fcf   bridge    bridge    local
76d9e06a360678e6c0b12b13d9cdde88cb63a77807012cb7e4e8b66bfd47e88b   host      host      local
9f44873071f4baa0f97756fd0b904cde51a718455689ccc58252d374b4d47992   none      null      local

2、查看网络详细信息

执行 docker network inspect 命令查看指定网络的详细信息。
参数可以是网络名称或网络ID。

# 语法
[root@localhost ~]# docker network inspect --help
Usage:  docker network inspect [OPTIONS] NETWORK [NETWORK...]
Display detailed information on one or more networks   
Options:
  -f, --format string   Format the output using the given Go template
  -v, --verbose         Verbose output for diagnostics                     # 诊断的详细输出


# 案例
[root@localhost ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "989e0968a6fe9b95dd76238e4707f40bc0cf288fd6b764acbd537954fd0e6fcf",
        "Created": "2022-04-19T21:56:32.999550849+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": {
            "15d605de252549571b613ec08b397af49060e1d6f1a45548f884a7d2de896c56": {
                "Name": "test-dns02",
                "EndpointID": "a474c3a28141e679b93f7c4d44616452114e310f5bf8f40560f3f73eb90a1f7f",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "24574957d30aab88b2b4ebcb98c0878470a78a05df03dfb86ad4078fabed1fe5": {
                "Name": "test-dns03",
                "EndpointID": "745a7c6b314b5963c6d134c148205fc0a215f1f3afb7948246a423088863ab4e",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            },
            "60e63a6f891f2b8a25847c410f35ca0c88f172c15edbb39fd3631a61b7fc5ad0": {
                "Name": "test-dns",
                "EndpointID": "08574b9714bb18374c24cddb340a932a332a9aeda71037548e5ea87966c904f8",
                "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": {}
    }
]

# --format筛选输出
[root@localhost ~]# docker network inspect --format='{{json .Options}}'   bridge
{"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"}
[root@localhost ~]# docker network inspect --format='{{json .Containers}}'   bridge

3、创建容器网络

使用 docker network create 命令创建容器网络。

# 语法
[root@localhost ~]# docker network create --help
Usage:  docker network create [OPTIONS] NETWORK
Create a network
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                                     # 指定子网中容器的IP地址范围
      --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                     # 子网

# 案例
[root@localhost ~]# docker network create --driver bridge hqs_net01
00c4ff496a7d44dda7e1913e6119d45064aba010b5210b0afee04c6eedbae6a3
[root@localhost ~]# docker network create --driver bridge --subnet 10.10.1.0/24 --gateway 10.10.1.254 hqs_net02
7fe5768c8e84d3befef561a8632c49bdeb194b440836bf7223d8d37e51ec2c8c
[root@localhost ~]# docker network ls
NETWORK ID     NAME        DRIVER    SCOPE
989e0968a6fe   bridge      bridge    local
76d9e06a3606   host        host      local
00c4ff496a7d   hqs_net01   bridge    local
7fe5768c8e84   hqs_net02   bridge    local
9f44873071f4   none        null      local

4、删除容器网络

使用 docker network rm 删除容器网络。

# 语法
[root@localhost ~]# docker network rm --help
Usage:  docker network rm NETWORK [NETWORK...]
Remove one or more networks
Aliases:
  rm, remove

# 案例
[root@localhost ~]# docker network rm c3f9bb71d92e
c3f9bb71d92e
[root@localhost ~]# docker network rm hqs_net01 hqs_net02
hqs_net01
hqs_net02

5、连接\断开容器网络

使用 docker network connect 连接容器网络。
使用 docker network disconnect 断开容器网络。

# 语法
[root@localhost ~]# docker network connect --help
Usage:  docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
      --alias strings           Add network-scoped               # 添加容器网络域关联
                                alias for the container
      --driver-opt strings      driver options for               # 网络驱动选项
                                the network
      --ip string               IPv4 address (e.g.,              # IPV4地址
                                172.30.100.104)
      --ip6 string              IPv6 address (e.g.,              # IPV6地址
                                2001:db8::33)
      --link list               Add link to another              # 添加到另一个容器的链接
                                container
      --link-local-ip strings   Add a link-local                 # 添加容器本地链接地址
                                address for the
                                container

[root@localhost ~]# docker network disconnect -h
Usage:  docker network disconnect [OPTIONS] NETWORK CONTAINER
Disconnect a container from a network
Options:
  -f, --force   Force the container to disconnect from a network     # 强制断开连接


# 案例
# 创建一个默认桥接网络的容器
[root@localhost ~]# docker run -tid centos
ac7b7e5e265a6bf72a48365045e9bfc91f86fa35a1e3f0d680da407491594206
# 创建自定义桥接网络
[root@localhost ~]# docker network create --driver bridge mynet
cdfcd6941400f9bebc5dbbd661e6584d39fbf59b2bf21f9480c6373a8ef5c7f5
# 断开默认桥接网络连接
[root@localhost ~]# docker network disconnect bridge ac7b7e5e265a
# 查看容器详情可发现网络配置和地址都消失
[root@localhost ~]# docker inspect ac7b7e5e265a
# 连接自定义桥接网络
[root@localhost ~]# docker network connect mynet ac7b7e5e265a
# 查看详情发现已经改为新网络配置
[root@localhost ~]# docker inspect --format="{{json .NetworkSettings.Networks}}"  ac7b7e5e265a
{"mynet":{"IPAMConfig":{},"Links":null,"Aliases":["ac7b7e5e265a"],"NetworkID":"cdfcd6941400f9bebc5dbbd661e6584d39fbf59b2bf21f9480c6373a8ef5c7f5","EndpointID":"4cbb484d4b92669d0a09d94224d1acc0e2c343a0bfa8e0329dccc5bd9fcae61d","Gateway":"172.19.0.1","IPAddress":"172.19.0.2","IPPrefixLen":16,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:ac:13:00:02","DriverOpts":{}}}

三、实验案例

1、容器连接默认的桥接网络

创建或启动容器时不指定网络,则该容器会被连接到默认桥接网络。
本实验,测试同一Docker主机两个容器间的通信。

# 1.查看当前已有的网络
[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
989e0968a6fe   bridge    bridge    local     《————默认桥接网络
76d9e06a3606   host      host      local
9f44873071f4   none      null      local

# 2.启动两个运行ash的alpine容器
# alpine镜像下载
[root@localhost ~]# docker pull alpine 
Using default tag: latest
latest: Pulling from library/alpine
df9b9388f04a: Pull complete 
Digest: sha256:4edbd2beb5f78b1014028f4fbb99f3237d9561100b6881aabbf5acce2c4f9454
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
# 启动容器
[root@localhost ~]# docker run -dti --name alpine1 alpine ash
f5116b60027b745495ad090de3e47e18b7b4ef27dd9529c0fc658f66febac044
[root@localhost ~]# docker run -dti --name alpine2 alpine ash
aa54330101c2bf5b09909ebbfbad18e316e6649305176e57db07842f3735e03f

# 3.检查容器是否启动
[root@localhost ~]# docker ps 
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
55f9241be324   alpine    "ash"     4 seconds ago   Up 3 seconds             alpine2
a654ec01f3eb   alpine    "ash"     7 seconds ago   Up 6 seconds             alpine1

# 4.查看bridge网络的详细信息
[root@localhost ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "989e0968a6fe9b95dd76238e4707f40bc0cf288fd6b764acbd537954fd0e6fcf",
        "Created": "2022-04-19T21:56:32.999550849+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": {
            "55f9241be324d8a2aba1c96c18fd762aa8c5940ff395a01ead8cb9824719b032": {
                "Name": "alpine2",
                "EndpointID": "c1b5d5ea6e1446b8f934e54a3461197f544eb13ef7f1e7350f6afe8836b7b3a7",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",                 《————第二个容器
                "IPv6Address": ""
            },
            "a654ec01f3eb117fbc4f4248b5e08aceb7ad37efbe7a228d998ac86a13b5a17a": {
                "Name": "alpine1",
                "EndpointID": "874a9857659ff2ea7d0004826b34058923806cae592951276c78a4f2bb72a391",
                "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": {}
    }
]

...

# 5.docker attach命令连接到alpine1容器 
[root@localhost ~]# docker attach alpine1            《————连接到alpine容器
/ # ip addr show                                      《———— ‘#’说明当前容器用户以root登录
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
19: eth0@if20: <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              《————地址为172.17.0.2
       valid_lft forever preferred_lft forever
/ # 

# 6.在alpine1容器ping外网
/ # ping -c 2 www.163.com
PING www.163.com (221.233.240.107): 56 data bytes
64 bytes from 221.233.240.107: seq=0 ttl=127 time=4.929 ms
64 bytes from 221.233.240.107: seq=1 ttl=127 time=5.103 ms

--- www.163.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 4.929/5.016/5.103 ms

# 7.在alpine1容器ping第二个容器
# (1)ping地址可以通
/ # ping -c 2 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.065 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.057 ms

--- 172.17.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.057/0.061/0.065 ms
# (2)ping名称不能通
/ # ping -c 2 alpine2
ping: bad address 'alpine2'

# 8.离开但不停止容器————输入 Ctrl+P 和 Ctrl+Q
/ # read escape sequence
[root@localhost ~]# docker ps 
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
55f9241be324   alpine    "ash"     9 minutes ago   Up 9 minutes             alpine2
a654ec01f3eb   alpine    "ash"     9 minutes ago   Up 9 minutes             alpine1

# 9.停止并删除容器
[root@localhost ~]# docker stop alpine1 alpine2
alpine1
alpine2
[root@localhost ~]# docker rm alpine1 alpine2
alpine1
alpine2

2、使用传统的容器连接

默认桥接网络的容器之间只能通过IP地址通信。
如要通过名称通信,可使用传统的 --link 选项添加到容器的连接。
本实验,在两个容器间建立连接,然后通过连接名称或别名访问源容器。

# 1.创建两个连接默认桥接网络的容器
[root@localhost ~]# docker run -dti --name alpine1 alpine ash
667caa0d0690c95de34e41bfebaf983e897f3a7e028fda892fca884f1f94dc49
# 创建容器时,添加到第一个容器的连接,并配置别名alp
[root@localhost ~]# docker run -dti --name alpine2 --link alpine1:alp alpine ash
21c0ddd94cb4d7190701d003868caef7cd9f82aded0ae0c5a2e9e68ebb45a03f

# 2.进入alpine2容器测试网络连通性
[root@localhost ~]# docker attach alpine2
/ # ping -c 2 alpine1
PING alpine1 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.048 ms
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.056 ms
--- alpine1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.048/0.052/0.056 ms
# 测试后,再通过ctrl+P+Q退出容器。

# 3.进入alpine1容器测试网络连通性
[root@localhost ~]# docker attach alpine1
/ # ping -c 2 alpine2
ping: bad address 'alpine2'
# 失败原因:--link只添加了单向通信,接受容器可以通过名称访问源容器,源容器不能通过名称访问接收容器。
# 测试后,再通过ctrl+P+Q退出容器。

# 4.删除容器恢复环境
[root@localhost ~]# docker rm -f $(docker ps -aq)
21c0ddd94cb4
667caa0d0690

3、创建用户自定义桥接网络并连接容器

实验:示范如何将容器连接到用户自定义桥接网络,并验证容器间的连通性。

在自定义桥接网络中,容器不仅能通过IP地址进行通信,还能将容器名称解析到IP地址,此功能称为自动服务发现(Automatic Service Discovery)。

# 1.创建用户自定义桥接网络
[root@localhost ~]# docker network create --driver bridge alpine-net
9e8a13047a172f4d3c8cdb10d16291f6889f40c4ea7e790e49e11dd6e6e7d00c

# 2.查看当前docker主机的网络
[root@localhost ~]# docker network ls
NETWORK ID     NAME         DRIVER    SCOPE
9e8a13047a17   alpine-net   bridge    local
# 查看新网络的详细信息
[root@localhost ~]# docker network inspect alpine-net
[
    {
        "Name": "alpine-net",
        "Id": "9e8a13047a172f4d3c8cdb10d16291f6889f40c4ea7e790e49e11dd6e6e7d00c",
        "Created": "2022-04-20T16:59:22.055790409+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": {}
    }
]

# 3.创建四个容器
# (1)2个只连接用户自定义桥接网络
[root@localhost ~]# docker run -dti --name alpine1 --network alpine-net alpine ash
22af8e376fef34108cf2058810b7edd05c148314354341c067ff45d6e7437f46
[root@localhost ~]# docker run -dti --name alpine2 --network alpine-net alpine ash
26f211048d9d857029ee9e038918c38b9ae19f698e1806adbc78ed0aca6f1aff

# (2)1个只连接默认桥接网络
[root@localhost ~]# docker run -dti --name alpine3 alpine ash
1078e18ff3a2d84b2ea97a612fd577ef142e5a954753169e95c4d9b2bd337c41

# (3)1个同时连接默认桥接网络和用户自定义网络
# docker run 命令执行只能连接一个网络
[root@localhost ~]# docker run -dti --name alpine4 --network alpine-net alpine ash
4b63cd8a7a1efcbeabcdfd12fdb8881d35ffe72e66ddec15fdf64825dcb1cf6a
# connet命令连接第二个网络
[root@localhost ~]# docker network connect bridge alpine4

# (4)查看当前正在运行的容器
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
4b63cd8a7a1e   alpine    "ash"     2 minutes ago   Up 2 minutes             alpine4
1078e18ff3a2   alpine    "ash"     3 minutes ago   Up 3 minutes             alpine3
26f211048d9d   alpine    "ash"     4 minutes ago   Up 4 minutes             alpine2
22af8e376fef   alpine    "ash"     4 minutes ago   Up 4 minutes             alpine1

# 4.查看bridge网络和alpine-net网络信息
# 查看bridge网络
[root@localhost ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "aefaa402b60d4b6f7f2515575ba2720f98eb8fd0c1ead0a8572442c098e52ed5",
        "Created": "2022-04-20T15:52:23.173167512+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": {
            "1078e18ff3a2d84b2ea97a612fd577ef142e5a954753169e95c4d9b2bd337c41": {
                "Name": "alpine3",
                "EndpointID": "1e19495d48d8e83cff4add4d8ad1570b24068fec17824cf4f499c56010831e52",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "4b63cd8a7a1efcbeabcdfd12fdb8881d35ffe72e66ddec15fdf64825dcb1cf6a": {
                "Name": "alpine4",
                "EndpointID": "d2cb2c81fe71d54c3fc39782755f0b0c86ce415c67205c159bf16fe3ebd76c24",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/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": {}
    }
]
# 查看alpine-net网络
[root@localhost ~]# docker network inspect alpine-net
[
    {
        "Name": "alpine-net",
        "Id": "9e8a13047a172f4d3c8cdb10d16291f6889f40c4ea7e790e49e11dd6e6e7d00c",
        "Created": "2022-04-20T16:59:22.055790409+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": {
            "22af8e376fef34108cf2058810b7edd05c148314354341c067ff45d6e7437f46": {
                "Name": "alpine1",
                "EndpointID": "b2f1d6d2ebf8cce71dddf0b23fb941d17a4d3e0c757bf33604d6d57f8b801665",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            },
            "26f211048d9d857029ee9e038918c38b9ae19f698e1806adbc78ed0aca6f1aff": {
                "Name": "alpine2",
                "EndpointID": "01a8b99524d4db9a820ffede79fbcc0b95ccc1c00ab2d87a9a236c9f67c04dec",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "4b63cd8a7a1efcbeabcdfd12fdb8881d35ffe72e66ddec15fdf64825dcb1cf6a": {
                "Name": "alpine4",
                "EndpointID": "c79921b791e45fc22dc8b3b3df06ffe45ffe97f8999a724c51bd8c53d358ebb0",
                "MacAddress": "02:42:ac:12:00:04",
                "IPv4Address": "172.18.0.4/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

# 5、alpine1网络测试
[root@localhost ~]# docker attach alpine1
/ # ping -c 2 alpine2
PING alpine2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.063 ms               《————用户自定义网络,支持自动服务发现
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.054 ms
--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.054/0.058/0.063 ms

/ # ping -c 2 alpine4
PING alpine4 (172.18.0.4): 56 data bytes
64 bytes from 172.18.0.4: seq=0 ttl=64 time=0.060 ms                《————用户自定义网络,支持自动服务发现
64 bytes from 172.18.0.4: seq=1 ttl=64 time=0.055 ms
--- alpine4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.055/0.057/0.060 ms

/ # ping -c 2 alpine3
ping: bad address 'alpine3'                                          《————alpine3不在用户自定义网络alpine-net中

/ # ping -c 2 172.17.0.2                                             《————不在一个网络中,名称和IP都不能ping通
PING 172.17.0.2 (172.17.0.2): 56 data bytes
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss

/ # ping www.baidu.com
PING www.baidu.com (103.235.46.39): 56 data bytes
64 bytes from 103.235.46.39: seq=0 ttl=127 time=248.724 ms
64 bytes from 103.235.46.39: seq=2 ttl=127 time=259.902 m
# 测试后,再通过ctrl+P+Q退出容器alpine1。

# 6.alpine4网络测试
# alpine4既连接了默认桥接网络,也连接了alpine-net网络,可以访问所有的容器。
[root@localhost ~]# docker attach alpine4
/ # ping -c 2 alpine1
PING alpine1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.046 ms                《————用户自定义网络,支持自动服务发现
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.052 ms
--- alpine1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.046/0.049/0.052 ms

/ # ping -c 2 alpine2
PING alpine2 (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.058 ms                《————用户自定义网络,支持自动服务发现
64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.053 ms
--- alpine2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.053/0.055/0.058 ms

/ # ping -c 2 alpine3                                               《————alpine3为默认桥接网络,不支持自动服务发现
ping: bad address 'alpine3'

/ # ping -c 2 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.065 ms                 《————alpine3为默认桥接网络,支持地址ping通
64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.060 ms
--- 172.17.0.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.060/0.062/0.065 ms

/ # ping -c 2 www.baidu.com
PING www.baidu.com (14.215.177.38): 56 data bytes
64 bytes from 14.215.177.38: seq=0 ttl=127 time=29.962 ms            《————能访问外网
64 bytes from 14.215.177.38: seq=1 ttl=127 time=30.115 ms
--- www.baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 29.962/30.038/30.115 ms

7.清理环境
[root@localhost ~]# docker rm -f $(docker ps -qa)
4b63cd8a7a1e
1078e18ff3a2
26f211048d9d
22af8e376fef
[root@localhost ~]# docker network rm alpine-net
alpine-net
posted @ 2022-04-12 16:41  休耕  阅读(1729)  评论(0编辑  收藏  举报