Docker之Docker网络

1. 理解Docker0


  • 清空所有环境
docker rm -f $(docker ps -aq)
docker rmi -f $(docker images -aq)

1.1 测试


  • 三个网络
    在这里插入图片描述

  • 问题:docker 是如何处理容器网络访问的?

    # 测试 进行一个tomcat
    docker run -d -P --name tomcat01 tomcat
    # 查看网络
    docker exec -it tomcat01 ip addr
    
  • 此时出现报错。这是版本不一致的缺失命令

    OCI runtime exec failed: exec failed: unable to start container process: exec: "ip": executable file not found in $PATH: unknown
    
  • 进入容器,更新所需的命令
    shell docker exec -it tomcat01 /bin/bash apt update && apt install -y iproute2
    在这里插入图片描述

  • 更新完成之后退出容器,再次输入docker exec -it tomcat01 ip addr 查看网络情况

  • 发现容器启动的时候会得到一个 eth0@if7 的 ip 地址,这是 docke r分配的
    在这里插入图片描述

  • 思考:Linux 能不能 ping 通容器内部? --可以
    在这里插入图片描述

  • 容器内部可以 ping 通外界吗?–可以

    # 进入容器之后需要执行以下命令
    
    apt-get update
    apt install iputils-ping
    apt install net-tools
    

    在这里插入图片描述

1.2 原理


  1. 我们没启动一个 docker 容器,docker 就会给 docker 容器分配一个 IP,我们只要安装了 docker,就会有一个网卡 docker0 桥接模式,使用的技术是 veth-pair 技术

    • 再次测试 ip addr ,发现多了一个ip
      在这里插入图片描述
  2. 在启动一个容器测试,发现又多了一对网卡
    在这里插入图片描述

    • 再次进入容器 tomcat2 内部更新命令资源,退出重新查看ip
    • 可以发现和上面的是能对应上的,所以说是一对网卡!
      在这里插入图片描述
  • 我们发现这个容器带的网卡,都是一对对的
  • veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连
  • 正因为有这个特性,利用 veth-pair 充当一个桥梁,连接各种虚拟网络设备的
  • OpenStac,Docker 容器之间的连接,OVS的连接,都是使用 veth-pair 技术
  1. 我们来测试一下 tomcat01 和 tomcat02 是否可以 ping 通
    # 进入容器更新命令资源
    docker exec -it tomcat02 /bin/bahs
    apt install iputils-ping
    
    # 更新完成后退出容器,输入ping命令
    docker exec -it tomcat02 ping 172.17.0.2
    
    在这里插入图片描述

结论:容器和容器之间是可以 ping 通的,并且是通过 docker0 而非直接连通

在这里插入图片描述

  • 所有的容器不指定网络的情况下,都是 docker0 路由的,docker 会给我们的容器分配一个默认的可用 ip

1.3 小结


  • Docker 使用的是 Linux 的桥接,宿主机是一个 Docker 容器的网桥 docker0
    在这里插入图片描述

  • Docker 中所有网络接口都是虚拟的(不需要考虑硬件因素),虚拟的转发效率高(内网传递文件)

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

  • 高可用!

思考一个场景:我们编写了一个微服务,database url=ip:项目不重启,但是数据ip换了,我们希望可以处理这个问题。故通过名字来进行访问容器。

2. -link


$ docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

# 运行一个tomcat03 --link tomcat02
$ docker run -d -P --name tomcat03 --link tomcat02 tomcat
e63b5bd877a4ece0c56101064bb2f653c5e01f83baef067d9c7cd0db87e63208

# 运行一个tomcat03 --link tomcat02 可以ping通
$ docker exec -it tomcat03 ping tomcat02

# 用tomcat02 ping tomcat03 ping不通

# 如果报错OCI错误,是因为容器没有安装ping命令,依次执行以下命令
apt-get update
apt install iputils-ping
apt install net-tools

在这里插入图片描述

探究

  • 查看网络详细信息。可以发现 link 链接的信息

    docker inspect tomcat03
    

    在这里插入图片描述

  • 查看本地网桥

    docker network inspect 网络id 网段
    

    在这里插入图片描述

  • 显示了三个容器的 ip 地址
    在这里插入图片描述

  • 查看 tomcat03 里面的/etc/hosts 发现又 tomcat02 的配置
    在这里插入图片描述

  • --link 本质就是在hosts 配置中添加映射

  • 现在使用 Docker 已经不建议使用--link

  • 自定义网络,不适用docker0

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

3. 自定义网络


  • 查看所有的 docker 网络
    在这里插入图片描述

3.1 网络模式


  • bridge:桥接 docker (默认,自己创建也是用 bridge 模式)
  • none:不配置网络,一般不用
  • host:和宿主机共享网络
  • container:容器网络联通(用的少!局限很大)

3.2 测试


  • 先清空所有的环境

    docker rm -f $(docker ps -aq)
    
  • 这时就恢复成只有五个网卡的状态

    在这里插入图片描述

3.3 自定义网络


# 我们直接启动的命令 --net bridge, 而这个就是我们的docker0
# bridge 就是docker0
$ docker run -d -P --name tomcat01 tomcat
等价于 => docker run -d -P --name tomcat01 --net bridge tomcat
# docker0,特点:默认,域名不能访问。--link可以打通连接,但是很麻烦!
# 我们可以 自定义一个网络
$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

在这里插入图片描述

$ docker network inspect mynet;

在这里插入图片描述

  • 启动两个 tomcat ,再次查看网络情况
docker run -d -P --name tomcat01 --net mynet tomcat
docker run -d -P --name tomcat02 --net mynet tomcat

docker network inspect mynet

在这里插入图片描述

  • 可以看到现在的两个容器,网卡是我们自定义的 ip 地址
    在这里插入图片描述

  • 在自定义的网络下,服务可以互相 ping 通,仅仅使用名字,无需 --link
    在这里插入图片描述

  • 我们自定的网络 docker 帮我们维护好了对应的关系,推荐我们平时这样使用网络!

好处

  • redis 不同的集群使用不同的网络,保证集群是安全和健康的
  • mysql 不同的集群使用不同的网络,保证集群是安全和健康的

4. 网络连通


  • docker0 和 mynet(自定义网络) 是无法直接连接的,并且也不能直接打通。若需要连通的话,要 connect 连接 docker0 的容器和 mynet 的网络

  • 但是在实际的工作中,比如我们部署了mysql 使用了一个网段。部署了tomcat 使用了另一个网段,两个网段之间肯定是不能互相连通的,但是tomcat和mysql又需要相互连通,我们就要使用网络连通。原理图如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 连通之后,发现 docker0 下的容器 tomcat1,直接被连到了 mynet 的网络下

  • 这就是一个容器两个 ip 地址!

  • 好比阿里云服务器,有一个公网 ip 和一个私网 ip

    docker run -d -P --name tomcat-net-01 tomcat
    docker run -d -P --name tomcat-net-02 tomcat
    docker network connect mynet tomcat1
    docker network inspect mynet
    

    在这里插入图片描述

  • docker0 下的 tomcat-net-01 连通加入后,此时,它已经可以和 mynet 下的 tomat01 ping 通了

  • 而 docker0 下的 tomcat-net-02 仍然是不通的

结论:假设要跨网络操作别人,就需要使用 docker net work connect 连通!

5. 实战:部署Redis集群


# 创建网卡
docker network create redis --subnet 172.38.0.0/16
# 通过脚本创建六个redis配置
for port in $(seq 1 6);\
do \ 
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF > /mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done

在这里插入图片描述

# 通过脚本运行六个redis
for port in $(seq 1 6); \
do \
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \
-v /mydata/redis/node-${port}/data:/data \
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \
done
# 进入其中一个容器
docker exec -it redis-1 /bin/sh
# 创建集群
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
  • docker 搭建 redis 集群完成!

  • 在另一个会话中停止 redis-3 ,再次去查找数据。可以发现集群里面的主机宕机后,投票选举除了一个新的主机。
    在这里插入图片描述

  • 我们使用docker 之后,所有的技术都会慢慢变得简单起来!

6. 总结


  • veth pair是成对出现的一种虚拟网络设备接口,一端连着网络协议栈,一端彼此相连。

  • docker中默认使用docker0网络

  • docker0相当于一个路由器的作用,任何一个容器启动默认都是docker0网络。

  • docker0是容器和虚拟机之间通信的桥梁。

  • 推荐使用自定义网络,更好实现使用服务名的连通方式,避免ip改变的尴尬。

  • 网络之间不能直接连通,网络连通是将一个容器和一个网络之间的连通,实现跨网络操作。

posted on 2023-04-23 11:24  JAVA开发区  阅读(18)  评论(0编辑  收藏  举报  来源