Windows docker网络详解

本文详细介绍了Windows和Linux环境下Docker网络的工作原理,特别是桥接模式(Bridge)及其与Docker0的关系,以及自定义网络的配置和区别。重点讲述了Docker0在容器通信中的角色以及其在不同网络模式下的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

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
Docker on Windows by Elton Stoneman English | 14 July 2017 | ISBN: 1785281658 | 358 Pages | AZW3/EPUB/MOBI/PDF (conv) | 23.77 MB Key Features Start building applications as Docker images and running containers in a Windows production environment Design and implement distributed applications that run across multiple networked containers Build a full Continuous Deployment pipeline for a .NET Core application running on Windows Book Description Docker has become hugely popular because it offers benefits at all stages of software design and delivery. Until recently, it was impossible to use a Windows Server platform to host the Docker Engine without adding an additional layer of virtualization. Starting with Windows Server 2016, you are able to use Docker on Windows and take advantage to easily build, deploy, and run Windows Containers. From building and running simple images to designing and implementing distributed applications, this book will teach everything you need to know while using Docker on Windows. You will start by installing Docker on different versions of Windows and Windows Server, and run a simple container to verify that the setup is working correctly. You will see how to build Docker images with a Dockerfile for a simple website, and then run it on Windows. Moving on, we'll cover the practical usage of Docker and the tools in the Docker ecosystem, such as Docker Compose, Docker Trusted Registry, and Docker Swarm Mode. Then, you'll be able to apply that knowledge by building a full continuous deployment pipeline for a .NET Core application running on Windows. We'll also dive deep into some of the core features of Docker, such as networking and security. At the end of the book, you'll be guided through a business case that will help you practically implement Docker in a real-world scenario. What you will learn Understand how Docker works, build images, and run containers Run Docker on different versions of Windows, and on the cloud with Azure Des
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值