docker网络详解

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

  • 作用: 指定网络驱动程序。
  • 说明: 此选项指定用于创建网络的网络驱动程序。可用的驱动程序包括 bridgeoverlaymacvlan 等。

--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网络详解

相关推荐
2403_875736878 分钟前
道品科技智慧农业中的自动气象检测站
网络·人工智能·智慧城市
MonkeyKing_sunyuhua26 分钟前
ubuntu22.04 docker-compose安装postgresql数据库
数据库·docker·postgresql
追风林1 小时前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
Tassel_YUE2 小时前
网络自动化04:python实现ACL匹配信息(主机与主机信息)
网络·python·自动化
€☞扫地僧☜€2 小时前
docker 拉取MySQL8.0镜像以及安装
运维·数据库·docker·容器
茶馆大橘2 小时前
微服务系列六:分布式事务与seata
分布式·docker·微服务·nacos·seata·springcloud
Diamond技术流2 小时前
从0开始学习Linux——网络配置
linux·运维·网络·学习·安全·centos
Spring_java_gg2 小时前
如何抵御 Linux 服务器黑客威胁和攻击
linux·服务器·网络·安全·web安全
全能全知者3 小时前
docker快速安装与配置mongoDB
mongodb·docker·容器
方方怪4 小时前
与IP网络规划相关的知识点
服务器·网络·tcp/ip