Docker 学习笔记(十一)-- Docker 网络

Docker 网络

什么是子网掩码?

用来判断两台计算机的 IP 地址是否属于同一个网络段的判断。如果两台计算机处于同一个网络字段上,则这两台计算机就可以直接进行通信交流。

将计算机的IP地址和子网掩码都转化为二进制,进行AND运算,得出结果相同的话,则说明两台计算机处在同一个网络段,可以直接通信。

IP 地址在设计时就考虑到地址分配的层次特点,将每个 IP地址都分割成网络号和主机号两部分,以便于 IP地址的寻址操作。

IP 地址的网络号和主机号各是多少位呢?如果不指定,就不知道哪些位是网络号、哪些是主机号,这就需要通过子网掩码来实现。

什么是网关?

通常指默认网关,比如通过子网掩码判断出两台计算机处于不同的网络字段,两台计算机就不能直接进行通信,为了能进行通信,这个时候网关就出现了,可以将不同网络频段的两台计算机联系在一起,从而进行通信。

网关实质上是一个网络通向其他网络的IP地址。比如有网络A和网络B,网络A的IP地址范围为“192.168.1.1192.168.1.254”,子网掩码为255.255.255.0;网络B的IP地址范围为“192.168.2.1192.168.2.254”,子网掩码为255.255.255.0。在没有路由器的情况下,两个网络之间是不能进行TCP/IP通信的,即使是两个网络连接在同一台交换机(或集线器)上,TCP/IP协议也会根据子网掩码(255.255.255.0)判定两个网络中的主机处在不同的网络里。而要实现这两个网络之间的通信,则必须通过网关。如果网络A中的主机发现数据包的目标主机不在本地网络中,就把数据包转发给它自己的网关,再由网关转发给网络B的网关,网络B的网关再转发给网络B的某个主机。网络B向网络A转发数据包的过程也是如此 所以说,只有设置好网关的IP地址,TCP/IP协议才能实现不同网络之间的相互通信。那么这个IP地址是哪台机器的IP地址呢?网关的IP地址是具有路由功能的设备的IP地址,具有路由功能的设备有路由器、启用了路由协议的服务器(实质上相当于一台路由器)、代理服务器(也相当于一台路由器)。

一文搞懂网络知识,IP、子网掩码、网关、DNS、端口号 - 知乎 (zhihu.com)

IP地址、子网掩码、网关的概念 - 知乎 (zhihu.com)

vmware虚拟机虚拟网卡作用_岁月的拓荒者的博客-CSDN博客

清空镜像和容器

# 删除所有容器
$ docker rm -f $(docker ps -aq)
# 删除所有镜像
$ docker rmi -f $(docker images -aq)

1、理解 Docker0

【计算机网络】你真的认识 ip addr 命令的输出内容吗?_见见大魔王的博客-CSDN博客

在这里插入图片描述

三个网络

Docker 如何处理容器网络访问的?

在这里插入图片描述

测试

# 启动一个 Tomcat 容器
[root@localhost /]$ docker run -d -P --name tomcat_01 tomcat:7.0

# 查看容器内部的网络信息 ip addr
# 发现容器启动时会得到一个 eth0@if7 的 IP网卡,docker 分配的!
[root@localhost /]$ docker exec -it tomcat_01 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
6: eth0@if7: <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
       
# Linux 可以 ping 通这个容器内的 IP  (docke0: 172.17.0.1)
[root@localhost /]$ ping -c3 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.068 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.053 ms

原理

Docker 网络模式详解及容器间网络通信 - 知乎 (zhihu.com)

1、Docker就会给新启动的Docker容器分配一个IP,只要安装了Docker就会有一个 Docker0 的虚拟网卡(bridge 网络模式),使用是的 evth-pair 技术!

再次使用 ip addr 命令:发现多了一个 vethd562aef@if6 虚拟网卡。

在这里插入图片描述

2、再启动一个容器,发现又多了一对网卡

在这里插入图片描述

Docker 守护进程创建了一个虚拟以太网桥 docker0,新建的容器会自动桥接到这个接口,附加在其上的任何网卡之间都能自动转发数据包。

守护进程会创建一对对等虚拟设备接口 veth pair,将其中一个接口设置为容器的 eth0 接口(容器的网卡),另一个接口放置在宿主机的命名空间中,以类似 vethxxx 这样的名字命名。同时,守护进程还会从网桥 docker0 的私有地址空间中分配一个 IP 地址和子网给该容器,并设置 docker0 的 IP 地址为容器的默认网关。

OpenStack,Docker容器之间的连接,OVS的连接,都是使用 eveth-pair 技术的!

3、测试容器 tomcat_01 是否够用 ping 通 tomcat_02

# 可以 ping 通
[root@localhost /]$ docker exec -it tomcat_01 ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data.
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.201 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.034 ms

在这里插入图片描述

4、删除 tomcat_01 容器

只要容器删除后,对应的一对网桥就没了

在这里插入图片描述

2、–link

思考一个场景,我们编写一个微服务,数据库连接地址 (datasource=ip:port/xxxx) 是使用 ip 的,如果 ip 变化就连不到了,那我们能不能使用服务名访问呢?实现高可用!
如:jdbc:mysql://mysql:3306,这样的话哪怕 mysql 重启,我们也不需要修改配置了!docker提供了 --link的操作!
(springcloud feign 通过服务名调用)

这种方式官方已不推荐使用,并且在未来版本可能会被移除 Legacy container links | Docker Documentation

docker run --link 可以用来连接两个容器,使得源容器(被链接的容器)和接收容器(主动去链接的容器)之间可以互相通信,并且接收容器可以获取源容器的一些数据,如源容器的环境变量。

[root@localhost ~]$ docker ps 
CONTAINER ID   IMAGE        COMMAND             CREATED          STATUS          PORTS                      NAMES
d219082f82b7   tomcat:7.0   "catalina.sh run"   32 seconds ago   Up 28 seconds   0.0.0.0:49153->8080/tcp   tomcat_01
eac028266f7a   tomcat:7.0   "catalina.sh run"   4 days ago       Up 2 seconds    0.0.0.0:49154->8080/tcp   tomcat_02

[root@localhost ~]$ docker exec -it tomcat_02 ping tomcat_01
ping: tomcat_01: No address associated with hostname
# 如何解决
[root@localhost ~]$ docker run -d -P --name tomcat_03 --link tomcat_02 tomcat:7.0
b887a2fe4fae5e968ed3aa7cca3e2ee28a46e529fc7a5677a1ccb73433aba1d4
[root@localhost ~]$ docker exec -it tomcat_03 ping tomcat_02
PING tomcat_02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat_02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.130 ms
64 bytes from tomcat_02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.141 ms

# 反向不能 ping 通
[root@localhost ~]$ docker exec -it tomcat_02 ping tomcat_03
ping: tomcat_03: No address associated with hostname

docker network

[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

Run 'docker network COMMAND --help' for more information on a command.
[root@localhost ~]$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
6563b3632046   bridge    bridge    local		# docker0
7c554362cbe4   host      host      local
8bfc4929b49e   none      null      local
[root@localhost ~]$ docker network inspect 6563b3632046
[
    {
        "Name": "bridge",
        "Id": "6563b3632046a5e5c450beb51bb2809729729acd10df165e1525795fc78c8c9d",
        "Created": "2022-07-13T21:36:06.791064532+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": {
            "b887a2fe4fae5e968ed3aa7cca3e2ee28a46e529fc7a5677a1ccb73433aba1d4": {
                "Name": "tomcat_03",
                "EndpointID": "7756d3303230523f56ee475c70386a6df2a2460383f134c1dd48dfd6cd915e2a",
                "MacAddress": "02:42:ac:11:00:04",
                "IPv4Address": "172.17.0.4/16",
                "IPv6Address": ""
            },
            "d219082f82b7c6e4a15661911263edbef83ee38966313ac8a888209aa71d293f": {
                "Name": "tomcat_01",
                "EndpointID": "1491bdebda43b92c4b82fb5d5683af937dca60a8343fb0f28a3f8ae947327dc6",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "eac028266f7a89bc1b013ddce9900015f24bc710df6e1bbc30325bb0292d137f": {
                "Name": "tomcat_02",
                "EndpointID": "eb4efed4bad97c379f394f3f0aa73140184ff9fbd512df5de0876965ccc51f8f",
                "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": {}
    }
]

docker inspect

其实tomcat03就是在本地配置了tomcat02的配置

[root@localhost ~]$ docker inspect tomcat_03 | grep Links -C 10
			.....
            "Links": [
                "/tomcat_02:/tomcat_03/tomcat_02"
            ],
			.....

查看 tomcat_03 下 host 配置文件:

[root@localhost ~]$ docker exec -it tomcat_03 cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.3	tomcat_02 eac028266f7a	# 配置了一个 hosts 地址
172.17.0.4	b887a2fe4fae
# --link的时候,直接把需要link的主机的域名和ip直接配置到了hosts文件中

本质: --link 就是我们在 host 文件中增加了一个 172.17.0.3 tomcat_02 eac028266f7a 的配置。

不建议使用原因

docker0问题:不支持容器名连接访问!

3、Docker 网络模式

查看所有的docker网络

# docker network --help
docker network ls
3.1、网络模式
网络模式配置说明
bridge模式–net=bridge为每一个容器分配、设置IP等,并将容器连接到一个 docker0 虚拟网桥。(默认模式)
none模式–net=none容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,IP等。
container模式–net=container:name/id新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。
host模式–net=host容器将不会虚拟出自己的网卡,配置自己的P等,而是使用宿主机的 IP和端口。
用户自定义–net=自定义网络用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络(一般用bridge模式)
1)bridge 网络模式

在该模式中,Docker 守护进程创建了一个虚拟以太网桥 docker0,新建的容器会自动桥接到这个接口,附加在其上的任何网卡之间都能自动转发数据包。
在这里插入图片描述

2)host 网络模式
  • 采用 host 网络模式的 Docker Container,可以直接使用宿主机的 IP 地址与外界进行通信,若宿主机的 eth0 是一个公有 IP,那么容器也拥有这个公有 IP。同时容器内服务的端口也可以使用宿主机的端口,无需额外进行 NAT 转换;
  • host 网络模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。

在这里插入图片描述

3)none 网络模式

none 网络模式即不为 Docker Container 创建任何的网络环境,容器内部就只能使用 loopback 网络设备,不会再有其他的网络资源。

4)container 网络模式

处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用 localhost 高效快速通信。

Container 网络模式即新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样两个容器除了网络方面相同之外,其他的如文件系统、进程列表等还是隔离的。

在这里插入图片描述

5)自定义网络

虽然 Docker 提供的默认网络使用比较简单,但是为了保证各容器中应用的安全性,在实际开发中更推荐使用自定义的网络进行容器管理,以及启用容器名称到 IP 地址的自动 DNS 解析。

从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过容器名称通信。方法很简单,只要在创建容器时使用 --name 为容器命名即可。
但是使用 Docker DNS 有个限制:只能在 user-defined 网络中使用。也就是说,默认的 bridge 网络是无法使用 DNS 的,所以我们就需要自定义网络。

4、自定义网络

# 删除所有容器
[root@localhost ~]$ docker rm -f $(docker ps -aq)
# 不配置网络时,也就相当于使用默认值: --net bridge 使用的是 docker0
[root@localhost ~]$ docker run -d -P --name tomcat_01 --net bridge tomcat:7.0
# docker0 网络的特点:默认的、域名访问不通、--link 打通连接

自定义网络测试

[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
      --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

自定义创建一个网络:

# 自定义创建一个网络
# --driver bridge			桥接模式
# --subnet 192.168.0.0/16	子网
# --gateway 192.168.0.1		网关
[root@localhost ~]$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
ec7457772ed8fde0da37b31d6108e34e2ed38633f3c90fe2a33d7eadb947c0b0
[root@localhost ~]$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
6563b3632046   bridge    bridge    local
7c554362cbe4   host      host      local
ec7457772ed8   mynet     bridge    local
8bfc4929b49e   none      null      local
# 查看自己创建的网络信息
[root@localhost ~]$ docker network inspect mynet
[
    {
        "Name": "mynet",
        "Id": "ec7457772ed8fde0da37b31d6108e34e2ed38633f3c90fe2a33d7eadb947c0b0",
        "Created": "2022-07-13T23:21:35.730196203+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

创建两个容器使用自定义的网络配置:

[root@localhost ~]$ docker run -d -P --name tomcat-net-01 --net mynet tomcat:7.0
e78f5e6d47285c1bcee60b7e4ab6eff6b8e093f7e53233599108e89bc9adc1a5
[root@localhost ~]$ docker run -d -P --name tomcat-net-02 --net mynet tomcat:7.0
2433c5af82baa0b149a98a688f32c9345acd97cfaa85d91d3e13547aeec74a54
# 再次查看自己创建的网络信息
[root@localhost ~]$ docker network inspect mynet

在这里插入图片描述

默认时是ping不通容器名的,使用自定义网络再来测试能否ping通容器:

[root@localhost ~]$ docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.156 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.064 ms
# 现在不使用 --link 也能 ping 通容器名了
[root@localhost ~]$ docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.152 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.061 ms

总结

我们自定义的网络docker都已经帮我们维护好了对应的关系。所以我们平时这样使用网络,不使用 –-link 也能使用容器名 ping 通.

好处: 不同的集群使用不同网段的网络,保证集群是安全和健康的!如redis集群、mysql集群等。

5、网络连通

在这里插入图片描述

测试

[root@localhost ~]$ docker run -d -P --name tomcat-01 tomcat:7.0
04f6ce534f7e07d82149c58b04ee3f2b05d98ccd34e02eb29337c6194fa50bc5
[root@localhost ~]$ docker run -d -P --name tomcat-02 tomcat:7.0
797f01a03d11acf8301d16af562704480c8496dd0610678d79cb33ae5e92c4ce
# 查看容器
[root@localhost ~]$ docker ps
CONTAINER ID   IMAGE        COMMAND             CREATED          STATUS          PORTS                     NAMES
797f01a03d11   tomcat:7.0   "catalina.sh run"   3 minutes ago    Up 3 minutes    0.0.0.0:49160->8080/tcp  tomcat-02
04f6ce534f7e   tomcat:7.0   "catalina.sh run"   3 minutes ago    Up 3 minutes    0.0.0.0:49159->8080/tcp  tomcat-01
2433c5af82ba   tomcat:7.0   "catalina.sh run"   23 minutes ago   Up 23 minutes   0.0.0.0:49158->8080/tcp  tomcat-net-02
e78f5e6d4728   tomcat:7.0   "catalina.sh run"   23 minutes ago   Up 23 minutes   0.0.0.0:49157->8080/tcp  tomcat-net-01

ping 不通:

[root@localhost ~]$ docker exec -it tomcat-01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

命令

[root@localhost ~]$ docker network --help
Usage:  docker network COMMAND
Commands:
  connect     Connect a container to a network

[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., 172.30.100.104)
      --ip6 string              IPv6 address (e.g., 2001:db8::33)
      --link list               Add link to another container
      --link-local-ip strings   Add a link-local address for the container

测试 : 打通 tomcat-01mynet

[root@localhost ~]$ docker network connect mynet tomcat-01
[root@localhost ~]$ docker network inspect mynet
# 连通之后就是将 tomcat-01 放到了 mynet 之下
# 一个容器两个ip地址,类似于阿里云服务一个公网ip,一个私网ip

在这里插入图片描述

测试能否 ping 通:

# tomcat-01 可以ping通
[root@localhost ~]$ docker exec -it tomcat-01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.285 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.060 ms

# tomcat-02 ping不通
[root@localhost ~]$ docker exec -it tomcat-02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

结论:如果要跨网络操作别人,就需要使用 docker network connect [OPTIONS] NETWORK CONTAINER 连通!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值