Skip to content

11 Docker 基础 - 容器网络互连

  • 在 Docker 中,容器之间的网络互连是非常重要的,因为它允许不同的容器之间进行通信和数据交换。

  • 默认情况下,所有容器都是以 bridge 方式连接到 Docker 的一个虚拟网桥上。

    docker network

Docker Network

docker network | Docker Docs

bash
 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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 52:54:00:3e:47:20 brd ff:ff:ff:ff:ff:ff
    altname enp0s5
    altname ens5
    inet 10.0.16.3/22 metric 100 brd 10.0.19.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe3e:4720/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:e8:29:8e:92 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
    inet6 fe80::42:e8ff:fe29:8e92/64 scope link
       valid_lft forever preferred_lft forever
5: veth5077d5d@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 2e:17:e8:34:a9:f6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::2c17:e8ff:fe34:a9f6/64 scope link
       valid_lft forever preferred_lft forever

 docker run -d \
  --name nginx \
  -p 80:80 \
  nginx # 启动一个 nginx 容器
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
1f7ce2fa46ab: Pull complete
9b16c94bb686: Pull complete
9a59d19f9c5b: Pull complete
9ea27b074f71: Pull complete
c6edf33e2524: Pull complete
84b1ff10387b: Pull complete
517357831967: Pull complete
Digest: sha256:e5c240a6604281581e9828af96485f7bcb9fce9e7b0e43b8189ea9f38495a4c9
Status: Downloaded newer image for nginx:latest
9c182ced195860db79c933385af4e9d03b727a3f5c34289b6b57c02e5d837c19

 dip nginx # 查看 nginx 容器的 IP
172.17.0.2

 docker run -d --name dockerfile-demo -p 8080:8080 demo:1.0 # 启动一个 dockerfile-demo 容器
6dfaae39e87c8c60167f97d15534022ba6c43c6828e864b576573bc17551623e

 dip dockerfile-demo # 查看 dockerfile-demo 容器的 IP
172.17.0.3

 dex dockerfile-demo ping 172.17.0.2 # 在 dockerfile-demo 容器中 ping nginx 容器
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.172 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.067 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.064 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.063 ms
^C
--- 172.17.0.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 81ms
rtt min/avg/max/mdev = 0.063/0.091/0.172/0.047 ms
  • 发现 nginx 容器和 dockerfile-demo 容器之间可以互联,没有问题。
  • 但是,容器的网络 IP 其实是一个虚拟的 IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个 IP,而在部署时很可能 MySQL 容器的 IP 会发生变化,连接会失败。
  • 所以,我们必须借助于 docker 的网络功能来解决这个问题。

常用命令

TIP

加入自定义网络的容器才可以通过容器名互相访问,否则只能通过 IP 访问。

命令说明文档地址
docker network create创建一个网络docker network create
docker network ls查看所有网络docs.docker.com
docker network rm删除指定网络docs.docker.com
docker network prune清除未使用的网络docs.docker.com
docker network connect使指定容器连接加入某网络docs.docker.com
docker network disconnect使指定容器连接离开某网络docker network disconnect
docker network inspect查看网络详细信息docker network inspect

自定义网络演示

创建一个网络

bash
 docker network create hmall # 创建一个自定义网络 hmall
7a1c8ced3c4c3c337d37bb0ad8f093cf1b5df5491b0df6079e5b0eff13d20f05

 docker network ls # 查看所有网络,发现多了一个 hmall 网络
NETWORK ID     NAME      DRIVER    SCOPE
d63a3b4e98da   bridge    bridge    local
7a1c8ced3c4c   hmall     bridge    local
425a483112a6   host      host      local
bbbc870dae7e   none      null      local

 dkpsf -a # 查看所有容器
CONTAINER ID   IMAGE      PORTS                                                  STATUS          NAMES
57c068845948   mysql      0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   Up 49 seconds   mysql
6dfaae39e87c   demo:1.0   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp              Up 11 minutes   dockerfile-demo
9c182ced1958   nginx      0.0.0.0:80->80/tcp, :::80->80/tcp                      Up 17 minutes   nginx
  • 通过 docker network create 命令创建了一个自定义网络 hmall
  • 通过 docker network ls 命令查看所有网络,发现多了一个 hmall 网络
    • bridge 网络:Docker 默认的网络。这是 Docker 安装后自动创建的网络,用于容器之间的通信。bridge 网络是在单个 Docker 主机上的本地范围内运行的,通过 NAT(Network Address Translation)技术将容器内部的 IP 地址映射到主机上,使得容器可以访问外部网络。
    • hmall 网络:我们为特定应用或服务创建的自定义网络。它使用 bridge 驱动程序,因此与默认的 bridge 网络类似。
    • host 网络:它使用 host 驱动程序。与默认的 bridge 网络不同,host 网络允许容器直接使用主机的网络命名空间,即它们共享主机的网络栈。这意味着容器可以直接使用主机的网络接口,不需要额外的端口映射。
    • none 网络:它使用 null 驱动程序。在 none 网络中,容器没有网络连接。这对于一些特殊的使用场景可能很有用,其中容器不需要网络连接,或者网络连接是通过其他手段设置的。
特点none 网络模式host 网络模式bridge 网络模式
网络连接无网络连接,容器内无法直接访问外部网络共享主机的网络命名空间,与主机网络一致容器连接到默认的 Docker 创建的网桥
IP 地址未分配 IP 地址与主机相同,共享主机的 IP 地址在独立的网络命名空间中分配唯一的 IP 地址
访问外部网络无法直接访问外部网络直接访问主机网络,无需端口映射通过 NAT 技术实现容器与外部网络的通信
适用场景不需要网络连接的容器,独立运行的工具或任务需要最大化性能和直接访问主机网络的应用多个容器需要在同一主机上相互通信的场景

已运行的容器添加到自定义网路

bash
 dk network connect hmall mysql --alias db # 将 mysql 容器添加到 hmall 网络,并设置别名为 db

 dk network connect hmall dockerfile-demo --alias demo # 将 dockerfile-demo 容器添加到 hmall 网络,并设置别名为 demo

 dex dockerfile-demo ping db # 在 dockerfile-demo 容器中 ping db 容器,也就是 mysql 容器
PING db (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.143 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.040 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=3 ttl=64 time=0.060 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=4 ttl=64 time=0.047 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=5 ttl=64 time=0.063 ms
^C
--- db ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 67ms
rtt min/avg/max/mdev = 0.040/0.070/0.143/0.038 ms

 dex dockerfile-demo ping mysql # 使用容器名 mysql 也可以 ping 通
PING mysql (172.18.0.2) 56(84) bytes of data.
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.048 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.061 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=3 ttl=64 time=0.052 ms
64 bytes from mysql.hmall (172.18.0.2): icmp_seq=4 ttl=64 time=0.064 ms
^C
--- mysql ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 52ms
rtt min/avg/max/mdev = 0.048/0.056/0.064/0.008 ms

总结

  • 在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身
  • 在同一个自定义网络中的容器,可以通过别名互相访问

启动容器时添加到自定义网路

bash
  docker run -d --name nginx1 --network hmall nginx # 启动一个 nginx 容器,并添加到 hmall 网络
6b06b91c8787e9d9e1109acbeb281c8852847350bbbdb64106557dd00586a0ea

 dex dockerfile-demo ping nginx1 # 在 dockerfile-demo 容器中 ping nginx1 容器
PING nginx1 (172.18.0.4) 56(84) bytes of data.
64 bytes from nginx1.hmall (172.18.0.4): icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from nginx1.hmall (172.18.0.4): icmp_seq=2 ttl=64 time=0.070 ms
64 bytes from nginx1.hmall (172.18.0.4): icmp_seq=3 ttl=64 time=0.068 ms
64 bytes from nginx1.hmall (172.18.0.4): icmp_seq=4 ttl=64 time=0.071 ms
^C
--- nginx1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 70ms
rtt min/avg/max/mdev = 0.068/0.080/0.111/0.017 ms

 dkNinc hmall # 查看 hmall 网络中的容器
57c0688459482dcc5ef9f87739a931aa2a070a8a20bf25409c082ac7cf8c5023: mysql
6b06b91c8787e9d9e1109acbeb281c8852847350bbbdb64106557dd00586a0ea: nginx1
6dfaae39e87c8c60167f97d15534022ba6c43c6828e864b576573bc17551623e: dockerfile-demo

访问自定义网络外的容器

bash
 dkNinc hmall # 查看 hmall 网络中的容器
57c0688459482dcc5ef9f87739a931aa2a070a8a20bf25409c082ac7cf8c5023: mysql
6b06b91c8787e9d9e1109acbeb281c8852847350bbbdb64106557dd00586a0ea: nginx1
6dfaae39e87c8c60167f97d15534022ba6c43c6828e864b576573bc17551623e: dockerfile-demo

 dex dockerfile-demo ping nginx # 在 dockerfile-demo 容器中 ping nginx 容器,发现 ping 不通
ping: nginx: Name or service not known

 dk network connect hmall nginx # 将 nginx 容器添加到 hmall 网络

 dex dockerfile-demo ping nginx # 在 dockerfile-demo 容器中 ping nginx 容器,可以 ping 通了
PING nginx (172.18.0.5) 56(84) bytes of data.
64 bytes from nginx.hmall (172.18.0.5): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from nginx.hmall (172.18.0.5): icmp_seq=2 ttl=64 time=0.059 ms
64 bytes from nginx.hmall (172.18.0.5): icmp_seq=3 ttl=64 time=0.066 ms
^C
--- nginx ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 29ms
rtt min/avg/max/mdev = 0.059/0.063/0.066/0.009 ms

 dkNinc hmall # 查看 hmall 网络中的容器
57c0688459482dcc5ef9f87739a931aa2a070a8a20bf25409c082ac7cf8c5023: mysql
6b06b91c8787e9d9e1109acbeb281c8852847350bbbdb64106557dd00586a0ea: nginx1
6dfaae39e87c8c60167f97d15534022ba6c43c6828e864b576573bc17551623e: dockerfile-demo
9c182ced195860db79c933385af4e9d03b727a3f5c34289b6b57c02e5d837c19: nginx

alias

bash
# 查看指定容器 ip
alias dip = docker inspect --format '\''{{ .NetworkSettings.IPAddress }}'\

# 进入容器
alias dex = docker exec -i -t

# 查看指定网络中的容器
dkNinc() {
  docker network inspect -f '{{ range $key, $value := .Containers }}{{ printf "%s: %s\n" $key .Name}}{{ end }}' $1
}

总结

  • 在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身
  • 加入自定义网络的容器才可以通过容器名互相访问
  • docker network create 创建一个自定义网络
  • docker network connect 将已经运行的容器添加到自定义网络
  • docker run --network hmall 将容器添加到自定义网络
  • docker network disconnect 将容器从自定义网络中移除
  • docker network inspect 查看网络详细信息
  • docker network ls 查看所有网络
  • docker network rm 删除指定网络
  • docker network prune 清除未使用的网络