Docker 学习 | 容器互联

225 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

Docker 学习 | 容器互联

本文研究 Docker两个容器之间如何通信的问题

--link

准备工作

  • 使用Docker 启动两个tomcat
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 tomcat

用Tomcat01 通过 服务名 Ping Tomcat02

docker exec -it tomcat01 ping tomcat02

结果我们发现 ping 不通

如何才能解决呢?

我们需要这两个容器服务进行网络连接~

思考一下以下场景, 我们编写了一个微服务, 数据库的URL地址为IP,但是数据库的IP换掉了,我们此时需要修改代码重启项目才能解决。那么,我们能不能通过服务名来进行对数据库的访问, 即使IP地址换了,也不影响我们的项目呢?

--link

# 通过 --link 实现容器联通
docker run -d -P --name tomcat03 --link tomcat02 tomcat

测试一下

$ docker exec -it tomcat03 ping tomcat02

# 结果: ping 通了

但是这样做会有很多坑, 而且很不方便,而且不可以反向Ping

需要在tomcat02 中 --link tomcat03 才能实现互联

查看Docker 网络

docker network ls

查看网卡里面的所有东西

docker network inspect NETWORK_ID

本质原理

--link 将tomcat02的地址 在tomcat03中的 hosts 中增加了映射~

就这? 真是开发中是不建议使用的

docker0 不支持容器名连接访问

自定义网络

容器互联

查看 docker 当前网络

docker network ls

docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
51e24adb9482   bridge    bridge    local
3db21d51de9c   host      host      local
8d20e8fd6793   none      null      local

移除网络

docker network rm <NAME>

网络模式

  • bridge: 桥接模式(默认, 自己创建也使用 bridge 模式)
  • none: 不配置网络
  • host: 主机模式: 与宿主机共享网络
  • container: 容器内网络连通

docker network --help

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

测试之前清空容器 docker rm -f $(docker ps -aq)

ip addr 查看宿主机当前网卡

$ 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:4c:83:06 brd ff:ff:ff:ff:ff:ff
    inet 10.0.8.10/22 brd 10.0.11.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe4c:8306/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:fc:84:98:fb 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:fcff:fe84:98fb/64 scope link 
       valid_lft forever preferred_lft forever

测试

# 我们直接启动的命令, 默认是有 --net bridge 的, 这个就是 Docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat

# Docker0 特点: 1.默认的 2.域名不能访问

我们可以自定义一个网络

docker create

docker network create --help

# 我们自定义一个网络
# docker network create 
# --driver bridge 
# --subnet 192.168.0.0/16
# --gateway 192.168.0.1
# mynet
$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 现在我创建了一个网络, driver 是桥接(bridge), 网络的名字叫 mynet, 子网 [192.168.0.0/16] 最多支持 65535 个网络, 默认路由网关 [192.168.0.1]
de55be69be90cc51324b0dfcd6b1a25bf4d5cc2f91569208025a9f068565a383
# 创建成功

# 查看
[root@VM-8-10-centos tomcat]$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
acaeca217cc5   bridge    bridge    local
3edbb9cd9ab0   host      host      local
de55be69be90   mynet     bridge    local  # mynet 网络创建成功
dad0ff6720e0   none      null      local

docker inspect mynet

[root@VM-8-10-centos tomcat]# docker inspect mynet
[
    {
        "Name": "mynet",
        "Id": "de55be69be90cc51324b0dfcd6b1a25bf4d5cc2f91569208025a9f068565a383",
        "Created": "2021-09-29T23:54:40.88159831+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": {}
    }
]
# 到此, 我们自己的网络就创建好了~

测试: 创建 Tomcat 容器并使用我们创建的网络

$ docker run -d -P --name tomcat-net-01 --net mynet mytomcat
$ docker run -d -P --name tomcat-net-02 --net mynet mytomcat

查看 mynet

$ docker inspect mynet

[
    {
        "Name": "mynet",
        "Id": "de55be69be90cc51324b0dfcd6b1a25bf4d5cc2f91569208025a9f068565a383",
        "Created": "2021-09-29T23:54:40.88159831+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,
        # 在此处 我们发现, mynet 网络下存在了 tomcat01 和 tomcat02 两个容器
        "Containers": {
            "52514945040be96967dbc982f4cbe86a07c6303b51931595c645fc8f0deb9570": {
                "Name": "tomcat-net-02",
                "EndpointID": "d2bcd6a479f20e20575c03d6309a0d2790d9867a47325f11c140db25e792569f",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            },
            "e629bb8bcd66a2f43dbb617d9decc35d40bd1678c81a217d159057a4443aed22": {
                "Name": "tomcat-net-01",
                "EndpointID": "e2e501168303a5e33464ba0fb4d8838bd6a6a9f09545026b7a900b4abb8833a4",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

测试 tomcat-net-01 能直接 ping 通 tomcat-net-02么~

$ 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.117 ms
64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.063 ms
64 bytes from 192.168.0.3: icmp_seq=4 ttl=64 time=0.056 ms
64 bytes from 192.168.0.3: icmp_seq=5 ttl=64 time=0.054 ms
64 bytes from 192.168.0.3: icmp_seq=6 ttl=64 time=0.058 ms
64 bytes from 192.168.0.3: icmp_seq=7 ttl=64 time=0.054 ms
64 bytes from 192.168.0.3: icmp_seq=8 ttl=64 time=0.047 ms
64 bytes from 192.168.0.3: icmp_seq=9 ttl=64 time=0.052 ms
^C
--- 192.168.0.3 ping statistics ---

Success!

自定义网络 docker 都已经帮我们维护好了对应的关系, 推荐这样使用网络