Windows上的docker与Linux上的docker底层技术有些许区别,但实现的效果大体上还是差不多的,本文将以windows的视角,Linux的原理来讲解Docker网络。docker的网络共有四种模式,主要讲解bridge桥接模式,这也是使用最多的模式。

  1. 桥接模式(Bridge) :桥接模式是 Docker 默认的网络模式。在桥接模式下,Docker 会为每个容器创建一个虚拟网络接口,并为容器分配一个独立的 IP 地址。容器可以通过桥接网络与主机以及其他容器进行通信。桥接模式适用于在单个主机上运行多个容器,并希望它们能够相互通信。

  2. 主机模式(Host) :主机模式将容器与主机共享网络栈,即容器将直接使用主机的网络接口和 IP 地址。这意味着容器可以通过主机的 IP 地址直接访问外部网络,而不需要进行端口映射。主机模式适用于需要容器与主机之间网络性能最大化的场景,但也可能导致容器之间的网络冲突。

  3. 容器模式(Container) :容器模式允许将一个容器的网络栈直接共享给另一个容器使用,而不是使用独立的网络栈。这些容器可以在同一个网络命名空间中运行,共享相同的 IP 地址和端口空间。容器模式适用于需要在容器之间共享网络栈的特定应用场景,例如微服务架构中的一组容器。

  4. 无网络模式(None) :无网络模式下,容器没有默认的网络连接。这意味着容器将无法通过网络访问外部资源,也无法通过网络与其他容器或主机进行通信。无网络模式适用于那些不需要网络连接的容器,例如批处理作业或仅限于本地访问的容器。

一、Windows上的  " Docker0 "

讲docker网络必然是和容器之间的通信相关的,那我们随便创建的两个容器是否能够相互通信呢,也就是说相互ping通呢?


在以上示例中,启动了两个centos的容器,并尝试了相互ping对方的ip地址,情况是能够ping通的,为什么?

在拥有物理网卡的计算机设备中,网卡可以保存其他主机网卡的Mac地址和IP地址,通过有线或无线的连接即可与其通信。

而容器是一个虚拟的概念,在计算机中可并没有特意为容器准备一个真实存在的网卡,然后这块网卡和其他的网卡进行有线或无线的连接。这也并不现实,容器会随时增加或删减,不可能每增加一个容器就在计算机中专门连接一根物理意义上的线。不过不能连物理的线,却是可以连虚拟的线,那么有以下两种连接方式,哪种更适合呢?

第一种 :在一个网络里每增加一个容器就在每个容器上增加一个虚拟网卡,然后相互连接。

第二种 :在网络中设置一个路由,每增加一个容器,在该路由和增加的容器上添加一块虚拟网卡,然后容器之间的通信由该路由进行转发。

很显然,第二种方式的实现会更加简单和有效,docker的桥接网络便是采用的第二种这个方式。在安装了docker的Linux系统上使用 ip addr 命令可以发现存在一个名为 docker0 的网卡,这个docker0便是上图中路由的角色。docker0这个网卡在windows上使用 ipconfig 的命令是无法查看到的,并且也不会显示每个容器上的虚拟网卡,这是因为Windows使用了NAT技术实现桥接网络,隐藏了许多细节。

不过在windows系统上没法直接找到docker0,但也是能找到一些他 "存在" 的证据的。在已经启动的两个centos容器中查看其ip地址和网关,可以发现,他们的网关都为相同的172.17.0.1,且他们的ip前缀都为172.17。这两个centos容器并没有刻意设置让他们处于同一个网段,但是他们确实就在同一个网段下。

实际上,这个网关 172.17.0.1 便是Windows上的 "docker0"。docker进程启动时,就会在主机上创建一个默认网关为 172.17.0.1的"docker0"虚拟网桥,只不过在windows上使用NAT技术将其细节隐藏了而已,一切使用默认桥接网络的容器在启动时会默认接在这个"docker0"的虚拟网桥上。

二、"Docker0"如何实现容器间的通信?

在不使用自定义网络下,每启动一个容器,docker进程就会给该容器分配一个ip地址,并且这个ip地址和默认桥接模式的网卡"docker0"处于同一网段下,使用的技术为veth-pair(Virtual Ethernet Pair)技术。

在centos容器内部使用 ip addr 可以查看到有一行 37: eth0@if38:

veth-pair 由一对虚拟网络接口组成:veth37 和 veth38。这两个接口是成对出现的,通过一个虚拟的以太网链路连接起来,用于连接各种虚拟设备。在这对接口中,veth37位于容器上,veth38位于"docker0"上。每启动一个容器,就会成对出现这两个接口,hsh_centos_2的接口序号为39、40,以下再开启一个hsh_centos_3 容器,其接口序号为41、42。

正常来说,veth的接口都是在主机上创建且可见的,只是Windows使用NAT技术隐藏了这些细节,而容器内部是基于linux实现的,所以能看见veth接口。

所以,在不使用自定义网络的情况下,默认桥接模式 "docker0" 实现容器间通信的流程就是:

  1. 打开docker进程,主机上便会自动创建一个"docker0"虚拟网桥。
  2. 创建容器时,主机会先创建好一对 veth-pair 虚拟接口,分别命名为veth37、veth38,将veth37接口放在容器上,veth38放在"docker0"上。
  3. 从"docker0"子网中分配一个IP给容器使用,并设置"docker0"的IP地址为容器的默认网关。"docker0"默认IP地址为172.17.0.1。
  4. 容器之间通信则通过默认的"docker0"进行转发。
  5. 容器删除,对应的veth-pair也会删除。

三、"Docker0"的缺点

  1. 使用默认网桥"docker0",只能通过ip地址相互访问
    docker创建容器分配的ip地址是会变化的,当你删除容器再重新启动时ip地址会不一样,这造成的问题就是,当"docker0"网络中其中一个容器存在问题删除重新启动后,其他所有的容器都会由于其ip地址变化而不认识他。可以使用--link解决该问题,但也需要双向连接,这种操作在集群中是非常麻烦的。
  2. 未指定的容器全部添加到"docker0"网络中,不方便管理也存在风险
    一般会使用"docker0"网络只是会在一些临时调试的容器中为方便而使用。
  3. 要从"docker0"网络中移除容器,只能将该容器删除

四、自定义网络

当使用自定义网络时,"docker0"就不适用了。docker的自定义网络模式共有四种,最常使用的为bridge模式,当自定义网络使用bridge模式时,原理和"docker0"是相同的,只是在其之上会提供更加完善的网络服务。

自定义网络和默认桥接网络"docker0"的区别:

  • 用户定义的网桥在容器之间提供自动的 DNS 解析功能。

    在默认的桥接网络上,容器之间只能通过 IP 地址相互访问,除非使用 --link 参数来创建手动链接,但这被认为是过时的。而在用户定义的网桥网络上,容器可以通过名称或别名相互进行 DNS 解析。

    一个具有前端 Web 服务和后端数据库的应用程序,如果在用户定义的网桥网络上运行这个应用程序的容器,无论应用程序堆栈在哪个 Docker 主机上运行,Web 容器都可以通过容器名称连接到数据库容器。

    相比之下,如果在默认的桥接网络上运行相同的应用程序堆栈,需要手动创建容器之间的链接,并且这些链接需要在双向上进行设置。这在有多个需要进行通信的容器时会变得非常复杂。或者,可以操作容器中的文件,但这可能导致难以调试的问题。
  • 用户定义的网桥提供了更好的隔离性。

    在默认情况下,所有未指定网络的容器都会连接到默认的桥接网络,这可能存在风险,因为不相关的堆栈、服务或容器之间可以进行通信。而使用用户定义的网络可以提供一个作用域限定的网络,只有连接到该网络的容器才能进行通信。
  • 使用用户定义的网络,容器可以动态地附加和分离。

    可以在容器的生命周期内动态地连接或断开容器与用户定义的网络的关联。而要从默认的桥接网络中删除容器,需要停止容器并使用不同的网络选项。
  • 每个用户定义的网络都会创建一个可配置的网桥。

    如果不同的应用程序组具有不同的网络需求,可以单独配置每个用户定义的网桥,在创建时进行设置。
  • 默认的桥接网络上的链接容器共享环境变量。

    初始时,唯一的共享环境变量方法是使用 --link 标志。然而,对于用户定义的网络,有更好的方法来共享环境变量。一些想法包括容器挂载共享的文件或目录,使用 Docker 卷进行共享,或者使用 Docker Compose 文件定义共享变量。

配置自定义网络的两种方式:

  1. 命令行

    docker network create

    常用可选项:
    --subnet      子网       192.168.0.0/16
    --driver        网络模式     bridge、host、none、container
    --gateway    网关ip    192.68.0.1
     docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 hsh_net_1


    接下来将之前的centos容器关闭,重新加上--net命令项使其使用刚刚配置的自定义网络。
     docker run -it --name="hsh_centos_1" --net hsh_net_1 centos /bin/bash
     docker run -it --name="hsh_centos_2" --net hsh_net_1 centos /bin/bash
     docker run -it --name="hsh_centos_3" --net hsh_net_1 centos /bin/bash

    以上三个centos容器的网段都在192.168.0.1下。

    通过 docker network inspect 命令可以查看自定义网络的情况。
    docker network inspect hsh_net_1



    可发现三个centos容器都已经包括在了hsh_net_1的自定义网络中。
    network其他相关命令

    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
  2. docker-compose

    具体配置方式参考 Docker compose介绍及入门、docker-compose.yaml文件如何编写及规范-CSDN博客
    docker-compose网络配置样例

    version: '3'
    networks:
      kafka-storm-net:
    services:
      zookeeper1:
        image: zookeeper:3.7.1
        container_name: zookeeper1
        hostname: zookeeper1
        ports:
          - 8101:2181
          - 8102:2888
          - 8103:3888
          - 8108:8080
        environment:
          ZOO_MY_ID: 1
          ZOO_SERVERS: server.1=zookeeper1:2888:3888;2181 server.2=zookeeper2:2888:3888;2181 server.3=zookeeper3:2888:3888;2181
        networks:
          - kafka-storm-net
      zookeeper2:
        image: zookeeper:3.7.1
        container_name: zookeeper2
        hostname: zookeeper2
        ports:
          - 8201:2181
          - 8202:2888
          - 8203:3888
          - 8208:8080
        environment:
          ZOO_MY_ID: 2
          ZOO_SERVERS: server.1=zookeeper1:2888:3888;2181 server.2=zookeeper2:2888:3888;2181 server.3=zookeeper3:2888:3888;2181
        networks:
          - kafka-storm-net
      zookeeper3:
        image: zookeeper:3.7.1
        container_name: zookeeper3
        hostname: zookeeper3
        ports:
          - 8301:2181
          - 8302:2888
          - 8303:3888
          - 8308:8080
        environment:
          ZOO_MY_ID: 3
          ZOO_SERVERS: server.1=zookeeper1:2888:3888;2181 server.2=zookeeper2:2888:3888;2181 server.3=zookeeper3:2888:3888;2181
        networks:
          - kafka-storm-net
      kafka1:
        image: bitnami/kafka:latest
        hostname: kafka1
        container_name: kafka1
        ports:
          - 19092:9092
        environment:
          KAFKA_ENABLE_KRAFT: yes
          KAFKA_CFG_NODE_ID: 1
          KAFKA_CFG_PROCESS_ROLES: controller,broker
          KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER
          KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: OUTSIDE:PLAINTEXT,CONTROLLER:PLAINTEXT,INSIDE:PLAINTEXT
          KAFKA_CFG_ADVERTISED_LISTENERS: OUTSIDE://:9092,INSIDE://:9091
          KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
          KAFKA_CFG_LISTENERS: CONTROLLER://:9093,OUTSIDE://0.0.0.0:9092,INSIDE://:9091
          KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
          ALLOW_PLAINTEXT_LISTENER: 'yes'
          KAFKA_KRAFT_CLUSTER_ID: iZWRiSqjZAlYwlKEqHFQWI
        volumes:
          - ./kafka-data/kafka1:/bitnami/kafka:rw
        networks:
          - kafka-storm-net
      kafka2:
        image: bitnami/kafka:latest
        hostname: kafka2
        container_name: kafka2
        ports:
          - 29092:9092
        environment:
          KAFKA_ENABLE_KRAFT: yes
          KAFKA_CFG_NODE_ID: 2
          KAFKA_CFG_PROCESS_ROLES: controller,broker
          KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER
          KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: OUTSIDE:PLAINTEXT,CONTROLLER:PLAINTEXT,INSIDE:PLAINTEXT
          KAFKA_CFG_ADVERTISED_LISTENERS: OUTSIDE://:9092,INSIDE://:9091
          KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
          KAFKA_CFG_LISTENERS: CONTROLLER://:9093,OUTSIDE://0.0.0.0:9092,INSIDE://:9091
          KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
          ALLOW_PLAINTEXT_LISTENER: 'yes'
          KAFKA_KRAFT_CLUSTER_ID: iZWRiSqjZAlYwlKEqHFQWI
        volumes:
          - ./kafka-data/kafka2:/bitnami/kafka:rw
        networks:
          - kafka-storm-net
      kafka3:
        image: bitnami/kafka:latest
        hostname: kafka3
        container_name: kafka3
        ports:
          - 39092:9092
        environment:
          KAFKA_ENABLE_KRAFT: yes
          KAFKA_CFG_NODE_ID: 3
          KAFKA_CFG_PROCESS_ROLES: controller,broker
          KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER
          KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: OUTSIDE:PLAINTEXT,CONTROLLER:PLAINTEXT,INSIDE:PLAINTEXT
          KAFKA_CFG_ADVERTISED_LISTENERS: OUTSIDE://:9092,INSIDE://:9091
          KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 1@kafka1:9093,2@kafka2:9093,3@kafka3:9093
          KAFKA_CFG_LISTENERS: CONTROLLER://:9093,OUTSIDE://0.0.0.0:9092,INSIDE://:9091
          KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE
          ALLOW_PLAINTEXT_LISTENER: 'yes'
          KAFKA_KRAFT_CLUSTER_ID: iZWRiSqjZAlYwlKEqHFQWI
        volumes:
          - ./kafka-data/kafka3:/bitnami/kafka:rw
        networks:
          - kafka-storm-net
      kafka-ui:
        image: provectuslabs/kafka-ui:master
        container_name: kafka-ui
        ports:
          - "9080:8080"
        restart: always
        environment:
          - KAFKA_CLUSTERS_0_NAME=hsh_kafka_cluster
          - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS= kafka1:9092 ,kafka2:9092,kafka3:9092
          - DYNAMIC_CONFIG_ENABLED= 'true' 
          - AUTH_TYPE=LOGIN_FORM  
          - SPRING_SECURITY_USER_NAME=hsh  
          - SPRING_SECURITY_USER_PASSWORD=241817 
        depends_on:
          - kafka1
          - kafka2
          - kafka3
        volumes:
          - ./kafka-ui/config.yml:/etc/kafkaui/dynamic_config.yaml
        networks:
          - kafka-storm-net
      storm-nimbus:
        image: storm:2.5.0
        container_name: storm-nimbus
        hostname: storm-nimbus
        command: storm nimbus
        ports:
          - 6627:6627
        depends_on:
          - zookeeper1
          - zookeeper2
          - zookeeper3
        environment:
          - STORM_ZOOKEEPER_SERVERS=zookeeper1,zookeeper2,zookeeper3
        volumes:
          - ./storm-conf/storm.yaml:/conf/storm.yaml
        networks:
          - kafka-storm-net
      storm-supervisor1:
        image: storm:2.5.0
        container_name: storm-supervisor1
        hostname: storm-supervisor1
        command: storm supervisor
        depends_on:
          - storm-nimbus
        volumes:
          - ./storm-conf/storm.yaml:/conf/storm.yaml
        networks:
          - kafka-storm-net
      storm-supervisor2:
        image: storm:2.5.0
        container_name: storm-supervisor2
        hostname: storm-supervisor2
        command: storm supervisor
        depends_on:
          - storm-nimbus
        volumes:
          - ./storm-conf/storm.yaml:/conf/storm.yaml
        networks:
          - kafka-storm-net
      storm-supervisor3:
        image: storm:2.5.0
        container_name: storm-supervisor3
        hostname: storm-supervisor3
        command: storm supervisor
        depends_on:
          - storm-nimbus
        volumes:
          - ./storm-conf/storm.yaml:/conf/storm.yaml
        networks:
          - kafka-storm-net
      storm-ui:
        image: storm:2.5.0
        container_name: storm-ui
        hostname: storm-ui
        command: storm ui
        ports:
          - "8080:8080"
        depends_on:
          - storm-nimbus
        volumes:
          - ./storm-conf/storm.yaml:/conf/storm.yaml
        networks:
          - kafka-storm-net
原创 YP小站 YP小站 来自专辑 Docker 问题使用阿里云ECS搭建 Harbor 服务( docker -compose 部署)遇到 网络 地址冲突,导致Harbor云主机ECS无法访问其它VPC网段云主机,这是为什么?使用 docker -compose 部署过Harbor同学都知道,在创建 Harbor 时,默认会创建 5个 网段,见下图。问题来了,因为使用阿里云 VPC 网络 ,网段为 172.16.... Docker file 是自定义镜像的一套规则,每一行代表一个指令,包含了构建镜像所需的指令和说明 Docker file镜像分层指的是 Docker 镜像构建过程中,每一条命令都是在上一条命令的基础上进行的,每一层都可以看作一个增量的变化,最终形成一个完整的镜像文件。常用指令名称描述语法语法描述示例FROM指定基础镜像,只能出现一次FROM [镜像名称]:[标签]其中,镜像名称是指要使用的 Docker 镜像的名称,标签用于指定具体的版本号。 docker windows docker -destop;安装redis;安装mysql;安装nacos;安装minio;安装xxl-job;使用 docker -compose管理 容器 Docker 允许开发中将应用、依赖、函数库、配置一起打包,形成可移植镜像 Docker 应用运行在 容器 中,使用沙箱机制,相互隔离可以将程序及其依赖、运行环境一起打包为一个镜像,可以迁移到任意Linux操作系统运行时利用沙箱机制形成隔离 容器 ,各个应用互不干扰启动、移除都可以通过一行命令完成,方便快捷。 Windows 10 Pro(专业版) / Enterprise(企业版) / Education(教育版)(1607 Anniversary Update、Build 14393 或者更新的版本)。 Windows 必须是 64 位的版本。需要启用 Windows 操作系统中的 Hyper-V 和 容器 特性。 -v a:b 本地磁盘与 容器 文件系统的映射. windows 盘符的d:需要转换为/d/. -it 分配一个伪中断, 使用标准输入流. reg. docker .alibaba-inc.com/dii/dii_alios7u2_dev ... 在上一章节已经成功的在Linux CentOS 8.4远程服务器中安装了 Docker ,下面让我们一起来试试如何在 Windows 10中安装 Docker 并运行起来。有人说你既然在Linxu环境中安装了 Docker 了,为什么还要到 Windows 环境中去折腾一个Dokcer环境呢?这不是在浪费时间内。 记得去配置一下阿里云加速的配置,不然你拉去镜像非常慢,话不多说,直接开始上手,建议把下文所有涉及到的命令自己敲一遍,下一篇还会降到 docker 高级用法,本篇只是基础入门!冲冲冲! 网络 模式桥接: docker 默认(自己创建也用)none:不配置 网络 host:和宿主机共享 网络 container: 容器 网络 连通(用的少)自定义 网络 使用自己的 网络 这样的话,只要是自己定义的 网络 ,都可以通过 容器 名字来ping通。