• 【Docker】docker网络


    🌳🌳【Docer篇整理】🌳🌳

    =========================
    篇一:docker核心概念与常用指令
    篇二:镜像与docker数据卷
    篇三:dockerfile
    篇四:docker网络

    1、Veth

    Veth是Linux中一种虚拟出来的网络设备,veth设备总是成对出现,所以一般也叫veth-pair。veth模拟了在物理世界里的两块网卡,以及一条网线。通过它可以将两个虚拟的设备连接起来,让他们之间相互通信。

    在这里插入图片描述
    如:v-a和v-b是一对veth设备,v-a收到的数据会从v-b发出。相反,v-b收到的数据会从v-a发出。Veth就像一根网线。

    在这里插入图片描述

    Veth设备的特点:

    • veth和其它的网络设备都一样,一端连接的是内核协议栈
    • veth设备是成对出现的,另一端两个设备彼此相连
    • 一个设备收到协议栈的数据发送请求后,会将数据发送到另一个设备上去

    在这里插入图片描述
    关于网桥在这里插入图片描述

    2、理解Docker0

    # 查询ip地址
    ip addr
    
    • 1
    • 2

    查询宿主机IP地址,可以看到这三个IP:

    在这里插入图片描述

    在宿主机启动一个容器:发现容器启动的时候得到一个eth0@if115 ip地址,这是docker分配的

    [root@9527 ~] docker run -d -P --name tomcat01 tomcat
     
    # 查看容器内部的网络地址 ip addr
    # 不用进入容器执行,就一句,直接跟后面
    [root@9527 ~] docker exec -it tomcat01 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
    114: eth0@if115: <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
     
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    思考: linux 宿主机能不能ping通这个容器?

    [root@9527 ~] 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.077 ms
    ...
     
    ==>linux 可以 ping 通docker容器内部!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    原理:

    • 每启动一个docker容器, docker就会给docker容器分配一个ip
    • 只要安装了docker,就会有一个网卡 docker0桥接模式,使用的技术是veth-pair技术

    上面容器启动后,ip addr 查看宿主机:发现多了一个网卡vethcf5ccc0,115和114刚好与容器中的114: eth0@if115相对应:

    在这里插入图片描述
    再启动一个容器测试, ip addr 查看宿主机发现又多了一对网卡:

    docker run -d -P --name tomcat02 tomcat
    
    • 1

    在这里插入图片描述

    这种容器带来的网卡,都是一对一对的,这就是evth-pair技术。

    # 我们发现这个容器带来网卡,都是一对对的
    # veth-pair 就是一对的虚拟设备接口,他们都是成对出现的,一端连着协议,一端彼此相连
    # 正因为有这个特性,veth-pair充当一个桥梁, 连接各种虚拟网络设备
    # OpenStac, Docker容器之间的链接,OVS的链接, 都是使用veth-pair技术
    
    • 1
    • 2
    • 3
    • 4

    测试tomcat01和tomcat02之间是否可以ping通:

    docker exec -it tomcat02 ping 172.17.0.2
    
    
    
    • 1
    • 2
    • 3

    发现容器和容器之间是可以ping通的,网络模型图如下:

    在这里插入图片描述

    结论:

    • tomcat01和tomcat02是共用的一个路由器,docker0

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

    这个可用IP的数量:
    以255.255.0.1/16为例
    00000000.00000000.00000000.00000000 (二进制下)
    转十进制则为255.255.255.255
    16即二进制下的前16位,即255.255.下是一个网络
    ===>
    可用IP有255 x 255 - 1 - 1 = 655355
    第一个1即0.0
    第二个1即255.255
    
    ---
    255.255.0.1/24 即只有最后的一位,255个IP是在这个网络范围的
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Docker使用的是Linux的桥接,宿主机中是一个Docker容器的网桥docker0
    在这里插入图片描述
    Docker中的所有的网络接口都是虚拟的,因为虚拟的转发效率高(参考内网传递文件!)

    3、- -link

    [root@9527 ~] docker exec -it tomcat02 ping tomcat01
    ping: tomcat01: Name or service not known
    
    
    • 1
    • 2
    • 3

    ping IP可以通,ping 容器名却不通,想实现通过容器名来互相访问,可以使用- -link

    [root@9527 ~] docker run -d -P  --name tomcat03 --link tomcat02 tomcat
    3a2bcaba804c5980d94d168457c436fbd139820be2ee77246888f1744e6bb473
    
    [root@9527 ~] docker exec -it tomcat03 ping tomcat02
    PING tomcat02 (172.17.0.3) 56(84) bytes of data.
    64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.129 ms
    64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.100 ms
    ...
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    反向可以ping通吗?----不能

    [root@iZ2zeg4ytp0whqtmxbsqiiZ ~] docker exec -it tomcat02 ping tomcat03
    ping: tomcat03: Name or service not known
    
    • 1
    • 2

    原因探究:

    在这里插入图片描述

    继续往下看inspect信息:看到docker为每个容器分配的IP地址

    在这里插入图片描述
    这个tomcat03能ping通tomcat02就是–link时在03本地hosts文件配置了tomcat02的IP和名字

    [root@9527 ~] docker exec -it tomcat03 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  tomcat02 f22ed47ed1be  ## !!!
    172.17.0.4  3a2bcaba804c
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    现在已经不建议使用–link了,往下看自定义网络

    4、自定义网络

    查看所有的docker网络

    docker network ls
    
    • 1

    在这里插入图片描述

    网络模式

    • bridge: 桥接模式,docker 默认的模式,自己创建的也是用brdge模式

    • none: 不配置网络

    • host: 主机模式,即和宿主机共享网络

    • container:容器网络连通(用的少,局限很大)

    # 直接启动的命令默认有一个 --net bridge,而这个就是我们的docker0
    docker run -d -P --name tomcat01 tomcat
    # 等价于
    docker run -d -P --name tomcat01 --net bridge tomcat
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    docker0特点,默认,容器名不能访问(加 --link可以打通连接,但不建议),基于这个情况,考虑使用自定义网络:

    自定义网络

    # --driver bridge
    # --subnet 192.168.0.0/16 可以支持255*255个网络 192.168.0.2 ~ 192.168.255.254
    # --gateway 192.168.0.1
    [root@9527 ~] docker network create --driver bridge 
    			--subnet 192.168.0.0/16 
    			--gateway 192.168.0.1 mynet
    26a5afdf4805d7ee0a660b82244929a4226470d99a179355558dca35a2b983ec
    [root@9527 ~] docker network ls
    NETWORK ID          NAME                DRIVER              SCOPE
    30d601788862        bridge              bridge              local
    226019b14d91        host                host                local
    26a5afdf4805        mynet               bridge              local
    7496c014f74b        none                null                local
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    创建成功,查看这个自定义网络的信息:

    docker network inspect mynet
    
    • 1

    在这里插入图片描述
    在自己创建的网络里面启动两个容器:

    [root@9527 ~] docker run -d -P --name tomcat-net-01 --net mynet tomcat
    
    [root@9527 ~] docker run -d -P --name tomcat-net-02 --net mynet tomcat
    
    # ping IP连接和bridge网络下一样
    [root@9527~] 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.
    ....
    
    # 现在不使用 --link,直接可以ping名字
    [root@9527~] docker exec -it tomcat-net-01 ping tomcat-net-02
    PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
     ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

    如此,不同的集群使用不同的网络,保证了集群是安全和健康的。如下图中的redis集群和mysql集群:

    在这里插入图片描述

    两个不同网络下的集群如何连通,看下面。

    5、网络连通

    在这里插入图片描述
    基于这个指令,测试在docker0和我自定义网络下的两个容器之间的连通:

    [root@9527 ~] docker network connect  mynet tomcat01
    
    • 1

    连通之后就是将tomcat01 放到了mynet网络下,简单讲就是一个容器两个ip地址 ,类比阿里云服务器,公网ip,私网ip

    [root@9527 ~] docker network inspect mynet 
    # 查看下mynet网络的变化
    # 看到tomcat01直接加入了mynet网络,拥有第二个IP
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    # 连通ok
    [root@9527 ~] docker exec -it tomcat01 ping tomcat-net-01
    PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
    ....
    
    # 换tomcat02依旧无法连通,没有connect
    [root@iZ2zeg4ytp0whqtmxbsqiiZ ~] docker exec -it tomcat02 ping tomcat-net-01
    ping: tomcat-net-01: Name or service not known
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结论:假设要跨网络 操作别的容器,就要使用docker network connect连通…!

    6、实战:部署Reids集群

    实验选定 三主三从 的结构,启动六个容器:

    在这里插入图片描述
    首先创建Redis集群的自定义网络:

    docker network create redis --subnet 172.38.0.0/16
    
    • 1

    接下来使用脚本直接创建六个Redis的配置:

    # 通过脚本创建六个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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    [root@9527 ~] ls /mydata/redis/
    node-1 node-2 node-3 node-4 node-5 node-6
    
    • 1
    • 2

    启动容器:

    # 创建结点1
    docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
    -v /mydata/redis/node-1/data:/data \
    -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
    -d 
    --net redis 
    --ip 172.38.0.11 
    redis:5.0.9-alpine3.11 
    redis-server /etc/redis/redis.conf
     
    #创建结点2
    docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
    -v /mydata/redis/node-2/data:/data \
    -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
    -d 
    --net redis 
    --ip 172.38.0.12 
    redis:5.0.9-alpine3.11 
    redis-server /etc/redis/redis.conf
    
    ....
    3、4、5、6的创建指令一样,改下端口和配置文件、映射目录就行
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    docker ps 可以看到六个容器启动成功(这里也感受到了容器的轻量级,起六个也没啥)

    在这里插入图片描述

    创建Redis集群:

    [root@9527 ~] docker exec -it redis-1 /bin/sh
    /data : ls
    appendonly.aof  nodes.conf
    /data : 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
    
    >>> Performing hash slots allocation on 6 nodes...
    Master[0] -> Slots 0 - 5460
    Master[1] -> Slots 5461 - 10922
    Master[2] -> Slots 10923 - 16383
    .....
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    等待搭建成功后,连接集群:

    [root@9527 ~] docker exec -it redis-1 /bin/sh
    /data : redis-cli - c # 注意加-c,即cluster
    127.0.0.1:6379> cluster info
    
    127.0.0.1:6379> cluster nodes
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    set一个值存入Redis:

    127.0.0.1:6379> set a b 
    -> Redirected to slot located at 172.38.0.13:6379
    OK
    
    • 1
    • 2
    • 3

    可以看到是13这台master处理了,此时停掉13,即redis-3容器

    [root@9527 ~] docker stop redis-3
    
    • 1

    模拟主节点挂了以后,此时再get刚存入的值,观察是否从机生效(选举):

    127.0.0.1:6379> get a  
    -> Redirected to slot located at 172.38.0.14:6379
    "b"
    
    • 1
    • 2
    • 3

    可以看到14做为13的从机,查数据仍然没问题!!

    在这里插入图片描述

    13failed,14成为master,集群部署成功!

    7、SpringBoot微服务打包成Docker镜像

    基本步骤是:

    • 敲代码,写Springboot项目
    • 打包应用
    • 编写Dockerfile
    • 构建镜像
    • 发布运行

    创建一个测试demo工程:

    在这里插入图片描述

    并新建一个controller

    @RestController
    public class HelloController{
    	
    	@GetMapping("/hello")
    	public String hello(){
    		return "hello,9527";
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    maven中的package打包:

    在这里插入图片描述

    本地测试jar包可正常启动,且能访问localhost:8080/hello

    在这里插入图片描述
    下载docker插件:
    在这里插入图片描述
    在这里插入图片描述

    下载完成后可连接远程仓库:

    在这里插入图片描述

    编写Dockerfile文件

    在这里插入图片描述

    这里先不CI/CD,直接把jar包和Dockerfile文件放到Linux宿主机,执行docker build

    [root@9527 ~] mkdir idea
    [root@9527 ~] cd idea
    [root@9527 idea] docker build -t code9527 .
    
    • 1
    • 2
    • 3

    镜像构建成功后,启动容器:

    [root@9527 idea] docker -d -P --name springboot-web code9527
    
    # 启动成功后,docker ps看到随机映射端口是32779
    [root@9527 idea] curl localhost:32779/test
    hello,9527
    [root@9527 idea] 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    成功!

    以后,交付的时候,交付一个镜像即可。部署时docker pull ,运行容器即可!当然实际开发需要CI/CD和K8s对大量容器进行编排。

    【Docker篇整理结束 2023/5/6 00:12】

    在这里插入图片描述

  • 相关阅读:
    母婴广告投放在哪里合适?如何在抖音投放广告抢占市场?
    tensor补充
    最新前端vue项目打包放到gitHub上部署步骤
    Hadoop之HDFS
    SOC验证环境的启动方式
    Kafka生产者之分区
    【实战项目开发技术分享】谈谈机器人如何进行脱困
    【Docker】Docker进阶(一)
    一级必杀,防不胜防的漏洞,WEB安全基础入门—文件上传漏洞
    hadoop配置nfs,window映射nfs
  • 原文地址:https://blog.csdn.net/llg___/article/details/130509519