深入浅出Docker原理及实战(五)——Docker网络介绍


声明:这是我在大学毕业后进入第一家互联网公司学习的内容


深入浅出Docker原理及实战系列第五篇,我主要分享Docker的网络概念及如何合理的使用Docker网络。

Docker网络介绍

Docker容器和服务如此强大的原因之一是您可以将它们连接在一起,或将它们连接到非Docker环境中。

Docker容器和服务甚至不需要知道它们已部署在Docker上,也不必知道它们的对等对象是否也是Docker中运行。

无论您的Docker主机运行Linux,Windows还是两者结合,您都可以使用Docker以与平台无关的方式管理它们。

网络模式简介

Docker的网络子系统可使用驱动程序插入。默认情况下,存在几个驱动程序,它们提供核心联网功能:

bridge(网桥)

默认的网络驱动程序。如果未指定驱动程序,则这是您正在创建的网络类型。当您的应用程序在需要通信的独立容器中运行时,通常会使用网桥网络。

host(主机网络)

对于独立容器,请删除容器与Docker主机之间的网络隔离,然后直接使用主机的网络。

overlay(覆盖网络)

覆盖网络将多个Docker守护程序连接在一起,并使群集服务能够相互通信。您还可以使用覆盖网络来促进群集服务和独立容器之间或不同Docker守护程序上的两个独立容器之间的通信。这种策略消除了在这些容器之间进行操作系统级路由的需要。

macvlan(物理地址网络)

Macvlan网络允许您将MAC地址分配给容器,使其在网络上显示为物理设备。Docker守护程序通过其MAC地址将流量路由到容器。macvlan 在处理希望直接连接到物理网络而不是通过Docker主机的网络堆栈进行路由的旧应用程序时,使用驱动程序有时是最佳选择。

none(禁用网络)

对于此容器,请禁用所有联网。通常与自定义网络驱动程序一起使用。none不适用于群体服务。

如何选型网络模式

  • 当您需要多个容器在同一Docker主机上进行通信时,最好使用用户定义的网桥网络。
  • 当容器的应用程序不能与Docker主机隔离时,但您希望容器的其他方面隔离时,主机网络是最佳选择。
  • 当您需要不同Docker主机上运行的容器进行通信时,或者当多个应用程序使用集群服务一起工作时,覆盖网络是最佳的选择。
  • 从VM设置迁移或需要容器看起来像网络上的物理主机(每个都有唯一的MAC地址)时,Macvlan网络是最好的。

4种网络模式

bridge networks

在网络方面,网桥是在网段之间转发流量的链路层设备。桥可以是在主机内核中运行的硬件设备或软件设备。

就Docker而言,网桥网络使用软件网桥,该软件网桥允许连接到同一网桥网络的容器进行通信,同时与未连接到该网桥网络的容器隔离。Docker网桥驱动程序会自动在主机中安装规则,以使不同网桥网络上的容器无法直接相互通信。

桥接网络适用于在同一 Docker守护程序主机上运行的容器。

启动Docker时,会自动创建一个默认的桥接网络(也称为bridge),并且除非另有说明,否则新启动的容器将连接到它。您还可以创建用户定义的自定义网桥网络。用户定义的网桥网络优于默认bridge 网络。

下面是一个默认网桥的例子

[root@localhost ~]# ip add

3: docker0:  mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:ec:96:8d:3a 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:ecff:fe96:8d3a/64 scope link 
       valid_lft forever preferred_lft forever
       
[root@localhost ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
45c686d33317        bridge              bridge              local

用户定义的网桥和默认网桥之间的区别

用户定义的网桥可在容器之间提供自动DNS解析

默认网桥上的容器只能通过IP地址相互访问,除非您使用–link选项。在用户定义的网桥网络上,容器可以通过名称或别名相互解析。

如果在默认网桥上运行相同的应用程序,则需要在容器之间手动创建链接(使用–link)。这些链接需要双向创建,因此您可以看到,要进行通信的容器超过两个,这将变得很复杂。或者,您可以修改/etc/hosts容器中的文件,但这会导致难以调试的问题。

想象一个具有Web前端和db后端的应用程序同时放在一个用户定义好的网桥上。如果容器web调用db,则db无论应用程序在哪个Docker主机上运行,Web容器都可以通过连接到db容器。

用户定义的网桥可提供更好的隔离

所有没有通过–network指定的容器都将连接到默认网桥网络。这可能是一种风险,因为不相关的应用/服务/容器随后能够进行通信。

自定义的网桥可提供局域网,其中只有连接到该网络的容器才能通信。

容器可以随时随地从用户定义的网络连接和分离

在容器的生命周期内,您可以即时将其与自定义的网桥连接或断开连接。要从默认网桥网络中删除容器,您需要停止容器并使用其他网络选项重新创建它。

每个用户定义的网络都会创建一个可配置的网桥

如果您的容器使用默认的网桥,则可以对其进行配置,但是所有容器都使用相同的设置,例如MTU和iptables规则。此外,配置默认桥接网络发生在Docker本身之外,并且需要重新启动Docker。

自定义的网桥是通过 docker network create创建和配置的。如果不同的应用程序组具有不同的网络要求,则可以在创建时分别配置每个自定义的网桥。

默认网桥网络上的链接容器共享环境变量

最初,在两个容器之间共享环境变量的唯一方法是使用–link链接它们。自定义网络无法进行这种类型的变量共享。但是,存在共享环境变量的高级方法。

  • 多个容器可以使用Docker卷挂载包含共享信息的文件或目录。
  • 使用可以一起启动多个容器docker-compose,并且compose文件可以定义共享变量(推荐配置)。
  • 您可以使用集群服务来代替独立容器,并利用共享配置(分布式共享)。

连接到同一自定义网桥的容器可以有效地将所有端口彼此公开。为了使容器或不同网络上的非Docker主机可以访问该端口,必须使用-p或–publish来发布该端口。

使用自定义网桥

使用docker network create命令创建自定义网桥,在不选择任何配置的情况创建的就是网桥模式,您还可以指定子网,IP地址范围,网关和其他选项。

docker network create my-net

使用docker network rm命令删除用户定义的网桥网络。如果容器当前已连接到网络,请先断开它们的连接。

docker network rm my-net
将容器连接到用户定义的网桥

创建新容器时,可以指定一个或多个–network参数。此示例将Nginx容器连接到my-net网络。它还将容器中的端口80发布到Docker主机上的端口8080,

因此外部客户端可以访问该端口。连接到my-net网络的任何其他容器都可以访问my-nginx容器上的所有端口,反之亦然。

docker create --name my-nginx \
  --network my-net \
  --publish 8080:80 \
  nginx:latest

要将运行中的容器连接到现有的用户定义的网桥,请使用docker network connect命令。以下命令将一个已经在运行的my-nginx容器连接到一个已经存在的my-net网络:

docker network connect my-net my-nginx
断开容器与用户定义的网桥的连接

要将运行中的容器与用户定义的网桥断开连接,请使用docker network断开命令。以下命令将my-nginx容器与my-net网络断开连接。

docker network disconnect my-net my-nginx

使用默认网桥

默认网桥被认为是Docker的遗留细节,不建议用于生产环境。对其进行配置需要手动操作,存在技术缺陷。

将容器连接到默认网桥

如果您未使用–network标志指定网络,而是指定了网络驱动程序,则默认情况下,您的容器将连接到默认网桥网络。除非使用旧版–link标志进行链接,否则连接到默认网桥网络的容器只能通过IP地址进行通信。

配置默认网桥网络

要配置默认的桥接网络,请在daemon.json中指定选项。这是一个daemon.json示例,其中指定了多个选项。仅指定您需要自定义的设置。

{
  "bip": "192.168.1.5/24",
  "fixed-cidr": "192.168.1.5/25",
  "fixed-cidr-v6": "2001:db8::/64",
  "mtu": 1500,
  "default-gateway": "10.20.1.1",
  "default-gateway-v6": "2001:db8:abcd::89",
  "dns": ["10.20.1.2","10.20.1.3"]
}

重新启动Docker以使更改生效。

网桥底层原理

创建或删除用户定义的网桥或将容器与用户定义的网桥连接或断开连接时,docker使用指定操作系统的工具来管理基础网络基础结构(例如,在Linux上添加或删除桥接设备或配置iptables规则)。这些细节应视为实施细节。让Docker为您管理用户定义的网络。

开启从Docker容器到外界的转发规则

默认情况下,来自连接到默认网桥网络的容器的流量不会转发到外界。要启用转发,您需要更改两个设置。这些不是Docker命令,它们会影响Docker主机的内核。

  • 配置Linux内核以允许IP转发
sysctl net.ipv4.conf.all.forwarding=1
  • 将iptables FORWARD策略的策略从DROP更改为ACCEPT
iptables -P FORWARD ACCEPT

这些设置不会在重新启动后持续存在,因此您可能需要将它们添加到启动脚本中。

overlay networks

覆盖网络驱动程序会在多个Docker守护程序主机之间创建一个分布式网络。该网络位于特定于主机的网络之上(覆盖主机网络),启用加密后,允许与其连接的容器(包括群集服务容器)进行安全通信。

Docker透明地处理每个数据包与正确的Docker守护程序主机和正确的目标容器之间的路由。

初始化群集或将Docker主机加入现有群集时,将在该Docker主机上创建两个新网络:

  • 一个名为Ingress的覆盖网络,用于处理与集群服务相关的控制和数据流量。创建群集服务并且不将其连接到用户定义的覆盖网络时,默认情况下它将连接到Ingress。
  • 一个名为docker_gwbridge的网桥网络,该网络将各个服务器Docker守护程序连接到该集群中的其他守护程序。

创建覆盖网络的先决条件

使用覆盖网络的Docker守护程序的防火墙规则
您需要打开以下端口,以往返于参与覆盖网络的每个Docker主机的流量:

  • 用于群集管理通信的TCP端口2377
  • TCP和UDP端口7946,用于节点之间的通信
  • UDP端口4789,用于覆盖网络流量

在创建覆盖网络之前,您需要使用初始化Docker守护程序作为swarm管理器,docker swarm init或者使用将该Docker守护程序加入现有的swarm docker swarm join。这两个都将创建默认的ingress覆盖网络,默认情况下,群集服务会使用该 覆盖网络。即使您从未计划使用群体服务,也需要这样做。之后,您可以创建其他用户定义的覆盖网络。

使用覆盖网络

官方文档讲了一个通俗易懂的例子:

需要三台物理或虚拟Docker主机,它们可以相互通信,并且都运行Docker 17.03或更高版本的新安装。本教程假定这三台主机在同一网络上运行,并且不涉及防火墙。

这些主机将被称为manager,worker-1和worker-2。该 manager主机将作为既是经理和工人,这意味着它可以运行服务任务和管理群。worker-1并且worker-2将作为唯一的工人

然后通过一系列命令,创建集群,加入集群,创建服务,连接服务即可。

看到这,如果你了解过kubernetes,是不是会发现Docker的覆盖网络和Kubernetes有异曲同工之妙,(虽然我还没仔细了解kubernetes的网络,但是我已经明显感觉到kubernetes就是加强版这种覆盖网络的使用,后期继续深挖主机之间的网络通信原理)

具体实现可以查看
覆盖网络官方教程

host networks

如果您对容器使用主机网络模式,则该容器的网络堆栈不会与Docker主机隔离(该容器共享主机的网络名称空间),并且该容器不会分配自己的IP地址。例如,如果您运行一个绑定到端口80 host 的容器并使用网络,则该容器的应用程序在主机IP地址上的端口80上可用。

注意!!!

由于使用时容器不拥有自己的IP地址 host模式的网络,端口映射不生效,并且-p,–publish,-P,和–publish-all选项都将被忽略,并且产生一个警告:

WARNING: Published ports are discarded when using host network mode

主机模式网络对于优化性能以及在容器需要处理大量端口的情况下很有用,因为它不需要网络地址转换(NAT),并且不会为每个端口创建"userland-proxy"。

通过将–network host传递给docker service create命令,您还可以将主机网络用于群集服务。在这种情况下,控制流量(与管理群集和服务有关的流量)仍会通过覆盖网络发送,但是单个群集服务容器会使用Docker守护程序的主机网络和端口发送数据。这带来了一些额外的限制。例如,如果服务容器绑定到端口80,则在给定的群集节点上只能运行一个服务容器。

主机网络官方教程

macvlan networks

某些应用程序,尤其是旧版应用程序或监视网络流量的应用程序,期望直接连接到物理网络。在这种情况下,可以使用macvlan网络驱动程序为每个容器的虚拟网络接口分配MAC地址,使其看起来像是直接连接到物理网络的物理网络接口。在这种情况下,您需要在Docker主机上指定用于macvlan的物理接口,以及的子网和网关。

您甚至可以macvlan使用不同的物理网络接口隔离网络。请记住以下几点:

  • 由于IP地址耗尽或“ VLAN扩散”,很容易无意间损坏您的网络,在这种情况下,您的网络中有大量不正确的唯一MAC地址。

  • 您的网络设备需要能够处理“混杂模式”,在该模式下,可以为一个物理接口分配多个MAC地址。

  • 如果您的应用程序可以使用网桥(在单个Docker主机上)或覆盖(跨多个Docker主机进行通信)工作,那么从长远来看,这些解决方案可能会更好。

具体实现可以看
macvlan网络官方教程

总结

对于Docker来说,掌握好网桥模式足够,覆盖网络会有更好的替代容器编排工具(k8s),mac网络和主机网络用的也较少。

Docker Network CLI

管理网络。您可以使用子命令来创建,检查,列出,删除,修剪,连接和断开网络连接。

用法:

docker network COMMAND

COMMAND子命令

COMMAND 描述
docker network connect 将容器连接到网络
docker network create 建立网络
docker network disconnect 断开容器与网络的连接
docker network inspect 显示网络的详细信息
docker network ls 列出网络
docker network rm 删除网络

docker network connect

将容器连接到网络

docker network connect [OPTIONS] NETWORK CONTAINER
OPTIONS 描述
–alias 为容器添加网络的别名
–driver-opt 网络的驱动程序选项
–ip 指定要分配给容器接口的IP地址
–link 将链接添加到另一个容器

例子:

  • 将正在运行的容器连接到网络
docker network connect redis-network redis
  • 启动容器时将其连接到网络
docker run -itd --network=redis-network redis
  • 指定容器在给定网络上将使用的IP地址
docker network connect --ip 172.18.1.2 redis-network redis
  • 为容器创建一个网络别名

–alias 选项可用于通过所连接网络中的另一个名称来解析容器。

docker network connect --alias redis6379 redis-network redis

处在redis-network这个网络中的容器可以通过redis6379去连接redis

  • 使用–link选项

您可以使用–link链接另一个具有首选别名的容器
docker network connect --link redis:redis6379 redis-network test

docker network create

创建一个新的网络。在DRIVER默认的网络驱动程序是bridge或者overlay。如果您安装了第三方或自己的自定义网络驱动程序,则也可以DRIVER在此处指定。如果未指定该 --driver选项,该命令将自动为您创建一个网桥。当您安装Docker Engine时,它会自动创建一个网桥。该网络对应于Docker Engine传统上依赖的网桥。当您启动一个新容器时, docker run它会自动连接到该网桥网络。您不能删除此默认网桥,但可以使用以下network create命令创建新的网桥。

docker network create [OPTIONS] NETWORK
OPTIONS 描述
–aux-address 网络驱动程序使用的辅助IPv4或IPv6地址
–driver , -d 默认是bridge 网络的驱动程序选项
–gateway 主子网的IPv4或IPv6网关
–internal 限制外部访问网络
–ip-range 从子范围分配容器ip
–subnet 代表网段的CIDR格式的子网

高级选项

网桥是单个引擎安装上的隔离网络。如果要创建一个跨越多个运行主机的Docker主机的overlay网络,则必须创建一个网络。与网桥不同,覆盖网络需要先存在一些先决条件才能创建一个。这些条件已经在上文讲过,不再重复,这里主要讲创建网桥的具体内容。

创建网络时,默认情况下,引擎会为该网络创建一个不重叠的子网。该子网不是现有网络的细分。它仅用于ip寻址目的。您可以覆盖此默认值,并使用该–subnet选项直接指定子网值。

例子

  • 在 bridge网络上,您只能创建一个子网:
 docker network create --driver=bridge --subnet=192.168.0.0/16 redis-network
  • 此外,还可以指定–gateway --ip-range和–aux-address 选项。
docker network create \
  --driver=bridge \
  --subnet=172.28.0.0/16 \
  --ip-range=172.28.5.0/24 \
  --gateway=172.28.5.254 \
  redis-network

docker network disconnect

断开容器与网络的连接,断开容器与网络的连接。容器必须正在运行才能将其与网络断开连接。

docker network disconnect [OPTIONS] NETWORK CONTAINER

--force , -f 强制容器断开网络连接

eg: docker network disconnect multi-host-network container1

docker network inspect

显示一个或多个网络详细信息,默认情况下,此命令将所有结果呈现在JSON对象中。

docker network inspect [OPTIONS] NETWORK [NETWORK...]

--format , -f  使用给定的Go模板格式化输出
--verbose , -v 	详细输出以进行诊断

docker network ls

列出daemon引擎知道的所有网络。这包括跨群集中多个主机的网络。

docker network ls [OPTIONS]
OPTIONS 描述
–filter , -f 提供过滤器值(例如“ driver = bridge”)
–format 使用Go模板的打印网络
–no-trunc 不要截断输出
–quiet , -q 仅显示网络ID

例子:

列出所有网络:

docker network ls
NETWORK ID          NAME                DRIVER          SCOPE
7fca4eb8c647        bridge              bridge          local
9f904ee27bf5        none                null            local
cf03ee007fb4        host                host            local
78b03ee04fc4        multi-host          overlay         swarm

使用--no-trunc选项显示完整的网络ID:

docker network ls --no-trunc
NETWORK ID                                                         NAME                DRIVER           SCOPE
18a2866682b85619a026c81b98a5e375bd33e1b0936a26cc497c283d27bae9b3   none                null             local
c288470c46f6c8949c5f7e5099b5b7947b07eabe8d9a27d79a9cbf111adcbf47   host                host             local
7b369448dccbf865d397c8d2be0cda7cf7edc6b0945f77d2529912ae917a0185   bridge              bridge           local
95e74588f40db048e86320c6526440c504650a1ff3e9f7d60a497c4d2163e5bd   foo                 bridge           local
63d1ff1f77b07ca51070a8c227e962238358bd310bde1529cf62e6c307ade161   dev                 bridge           local

过滤器匹配基于其驱动程序的网络。
docker network ls --filter driver=bridge
NETWORK ID          NAME                DRIVER            SCOPE
db9db329f835        test1               bridge            local
f6e212da9dfd        test2               bridge            local


docker network rm

按名称或标识符删除一个或多个网络。要删除网络,必须首先断开连接到它的所有容器。

docker network rm NETWORK [NETWORK...]

例子:

docker network rm my-network

Docker和Iptables(重中之重)

在Linux上,Docker操纵iptables规则以提供网络隔离。尽管这是实现的详细信息,并且您不应修改Docker在iptables策略中插入的规则,但是如果您想要拥有自己的策略(而不是由Docker管理的策略),它确实会对您需要执行的操作产生一些影响。

如果您在已暴露网络的主机上运行Docker,则可能需要采用iptables策略,以防止未经授权访问您主机上运行的容器或其他服务。下面主要描述如何实现此目标以及需要注意的注意事项。

启动Docker之前添加iptables策略

Docker安装了两个iptables链,名叫DOCKER-USER 和DOCKER,它确保传入的数据包始终首先由这两个链进行检查。

手动或通过其他基于iptables的防火墙添加到FORWARD链中的规则在这些链之后进行评估。这意味着,如果您通过Docker公开端口,则无论防火墙配置了什么规则,该端口都会公开。如果您希望即使在通过Docker公开端口时也要应用这些规则,则必须将这些规则添加到DOCKER-USER链中。

限制与Docker主机的连接

默认情况,允许所有外部IP连接到Docker主机。

要仅允许特定的IP或网络访问容器,请在DOCKER-USER过滤器链的顶部插入一个否定的规则。例如,下面一个规则限制了除192.168.1.1之外的所有IP地址的外部访问,也就是说只能有192.168.1.1才能访问这个容器内部

iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.1 -j DROP

请注意,您将需要更改ext_if以与主机的实际外部接口相对应。您可以改为允许来源子网的连接。以下规则仅允许从子网192.168.1.0/24访问容器内部:

iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.0/24 -j DROP

iptables是复杂的,更复杂的规则不在此主题范围内。有关它的更多信息,请参见Netfilter.org HOWTO。

还有几种策略具体请看 Docker和iptables

问题回顾

正好前几天出现了一个Docker的网络问题,无法启动容器,现在来回顾一下

为了证明启动Docker之前添加iptables策略这点非常重要,我做了以下实验。

  • 这台主机在启动docker之前已经关闭了防火墙,并且已运行了几个容器,执行iptables 命令查看链路信息 发现存在各个容器暴露端口的链路规则
[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
DOCKER-USER  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain DOCKER (2 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             172.17.0.2           tcp dpt:6379
ACCEPT     tcp  --  anywhere             172.18.0.2           tcp dpt:17010
ACCEPT     tcp  --  anywhere             172.18.0.2           tcp dpt:ups-onlinet
ACCEPT     tcp  --  anywhere             172.18.0.3           tcp dpt:17011
ACCEPT     tcp  --  anywhere             172.18.0.3           tcp dpt:talon-disc
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:17012
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:talon-engine
ACCEPT     tcp  --  anywhere             172.18.0.5           tcp dpt:17013
ACCEPT     tcp  --  anywhere             172.18.0.5           tcp dpt:microtalon-dis
ACCEPT     tcp  --  anywhere             172.18.0.6           tcp dpt:17014
ACCEPT     tcp  --  anywhere             172.18.0.6           tcp dpt:microtalon-com
ACCEPT     tcp  --  anywhere             172.18.0.7           tcp dpt:17015
ACCEPT     tcp  --  anywhere             172.18.0.7           tcp dpt:talon-webserver

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination         
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere       
  • 开启防火墙,执行iptables 命令查看链路信息 发现iptables好像恢复出厂默认了
[root@localhost ~]# systemctl start firewalld
[root@localhost ~]# iptables -L


Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere            
INPUT_direct  all  --  anywhere             anywhere            
INPUT_ZONES_SOURCE  all  --  anywhere             anywhere            
INPUT_ZONES  all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere            
FORWARD_direct  all  --  anywhere             anywhere            
FORWARD_IN_ZONES_SOURCE  all  --  anywhere             anywhere            
FORWARD_IN_ZONES  all  --  anywhere             anywhere            
FORWARD_OUT_ZONES_SOURCE  all  --  anywhere             anywhere            
FORWARD_OUT_ZONES  all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere             ctstate INVALID
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
OUTPUT_direct  all  --  anywhere             anywhere            

Chain FORWARD_IN_ZONES (1 references)
target     prot opt source               destination         
FWDI_public  all  --  anywhere             anywhere            [goto] 
FWDI_public  all  --  anywhere             anywhere            [goto] 

Chain FORWARD_IN_ZONES_SOURCE (1 references)
target     prot opt source               destination         

Chain FORWARD_OUT_ZONES (1 references)
target     prot opt source               destination         
FWDO_public  all  --  anywhere             anywhere            [goto] 
FWDO_public  all  --  anywhere             anywhere            [goto] 

Chain FORWARD_OUT_ZONES_SOURCE (1 references)
target     prot opt source               destination         

Chain FORWARD_direct (1 references)
target     prot opt source               destination         

Chain FWDI_public (2 references)
target     prot opt source               destination         
FWDI_public_log  all  --  anywhere             anywhere            
FWDI_public_deny  all  --  anywhere             anywhere            
FWDI_public_allow  all  --  anywhere             anywhere            
ACCEPT     icmp --  anywhere             anywhere            

Chain FWDI_public_allow (1 references)
target     prot opt source               destination         

Chain FWDI_public_deny (1 references)
target     prot opt source               destination         

Chain FWDI_public_log (1 references)
target     prot opt source               destination         

Chain FWDO_public (2 references)
target     prot opt source               destination         
FWDO_public_log  all  --  anywhere             anywhere            
FWDO_public_deny  all  --  anywhere             anywhere            
FWDO_public_allow  all  --  anywhere             anywhere            

Chain FWDO_public_allow (1 references)
target     prot opt source               destination         

Chain FWDO_public_deny (1 references)
target     prot opt source               destination         

Chain FWDO_public_log (1 references)
target     prot opt source               destination         

Chain INPUT_ZONES (1 references)
target     prot opt source               destination         
IN_public  all  --  anywhere             anywhere            [goto] 
IN_public  all  --  anywhere             anywhere            [goto] 

Chain INPUT_ZONES_SOURCE (1 references)
target     prot opt source               destination         

Chain INPUT_direct (1 references)
target     prot opt source               destination         

Chain IN_public (2 references)
target     prot opt source               destination         
IN_public_log  all  --  anywhere             anywhere            
IN_public_deny  all  --  anywhere             anywhere            
IN_public_allow  all  --  anywhere             anywhere            
ACCEPT     icmp --  anywhere             anywhere            

Chain IN_public_allow (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh ctstate NEW

Chain IN_public_deny (1 references)
target     prot opt source               destination         

Chain IN_public_log (1 references)
target     prot opt source               destination         

Chain OUTPUT_direct (1 references)
target     prot opt source               destination      
  • 关闭防火墙,执行iptables 命令查看链路信息
    发现iptables链路信息全部被清空
  • 启动容器 暴露80端口,发现启动失败
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 


[root@localhost ~]# docker  run  -d -p 80:80 --volumes-from pmm-data --name pmm-server --restart always  percona/pmm-server:latest
f86d559846840468a45ec4b69b3cd4458854b2e9392e4e47b84430e420c59f7c
docker: Error response from daemon: driver failed programming external connectivity on endpoint pmm-server (b5e49ead04279b9c1ab16609ed3fcb78d309fb2fcab001adda57a9bd45dc23d0):  (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 80 -j DNAT --to-destination 172.17.0.3:80 ! -i docker0: iptables: No chain/target/match by that name.
 (exit status 1)).
  • 重启docker服务端,执行iptables 命令查看链路信息,发现重新录入docker策略
[root@localhost ~]# systemctl restart docker
[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
DOCKER-USER  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain DOCKER (2 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             172.18.0.2           tcp dpt:17014
ACCEPT     tcp  --  anywhere             172.18.0.2           tcp dpt:microtalon-com
ACCEPT     tcp  --  anywhere             172.18.0.3           tcp dpt:17015
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:17010
ACCEPT     tcp  --  anywhere             172.18.0.5           tcp dpt:17012
ACCEPT     tcp  --  anywhere             172.18.0.3           tcp dpt:talon-webserver
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:ups-onlinet
ACCEPT     tcp  --  anywhere             172.18.0.5           tcp dpt:talon-engine
ACCEPT     tcp  --  anywhere             172.18.0.6           tcp dpt:17013
ACCEPT     tcp  --  anywhere             172.18.0.7           tcp dpt:17011
ACCEPT     tcp  --  anywhere             172.18.0.6           tcp dpt:microtalon-dis
ACCEPT     tcp  --  anywhere             172.18.0.7           tcp dpt:talon-disc

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination         
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere    

总结

你一定要在启动Docker之前关闭防火墙,否则重新启动防火墙再关闭也不会让iptables加入Docker链,唯一的解决办法就是重启Docker,这对于生产环境来说是极为危险的(你这台机器上的所有容器都得重启)

总结归纳

容器网络

容器使用的网络类型,无论是网桥,主机网络, 覆盖网络,macvlan网络还是自定义网络插件,在容器内部都是透明的。从容器的角度来看,它具有一个带有IP地址,网关,路由表,DNS服务和其他网络详细信息的网络接口(假定容器未使用none网络驱动程序)。

发布端口

默认情况下,创建容器时,它不会将其任何端口发布到外界。要使端口可用于Docker外部的服务或未连接到容器网络的Docker容器,请使用 --publish或-p标志。这将创建一个防火墙规则,该规则将容器端口映射到Docker主机上的端口。这里有些例子。

标志值 描述
-p 8080:80 将容器中的TCP端口80映射到Docker主机上的端口8080。
-p 192.168.1.100:8080:80 将容器中的TCP端口80映射到Docker主机上的端口8080,以连接到主机IP 192.168.1.100。
-p 8080:80/udp 将容器中的UDP端口80映射到Docker主机上的端口8080。
-p 8080:80/tcp -p 8080:80/udp 将容器中的TCP端口80映射到Docker主机上的TCP端口8080,并将容器中的UDP端口80映射到Docker主机上的UDP端口8080。

容器的IP地址和主机名

默认情况下,为容器连接到的每个Docker网络分配一个IP地址。IP地址是在网络池中分配的,因此Docker守护程序实际上充当了每个容器的DHCP服务器。每个网络还具有默认的子网掩码和网关。

容器启动时,只能使用将该容器连接到单个网络 --network。但是,您可以使用将运行中的容器连接到多个网络docker network connect。使用–network标志启动容器时 ,可以使用–ip或–ip6标志指定分配给该网络上的容器的IP地址。

使用将现有容器连接到其他网络时 docker network connect,可以在该命令上使用–ip或–ip6标志来指定其他网络上容器的IP地址。

同样,容器的主机名默认为Docker中容器的ID。您可以使用覆盖主机名–hostname。使用来连接到现有网络时docker network connect,可以使用该–alias 标志为该网络上的容器指定其他网络别名。

DNS服务

默认情况下,容器会继承/etc/resolv.conf配置文件中定义的主机的DNS设置 。使用默认网桥的容器将获得此文件的副本,而使用自定义网桥的容器将使用 Docker的嵌入式DNS服务器,该服务器会将外部DNS查找转发到主机上配置的DNS服务器。

自定义主机中定义的/etc/hosts不会继承。要将其他主机传递到您的容器中,请参考docker run 的参数设置。

Iptables

重要的事情说三次,你一定要在启动Docker之前关闭防火墙,你一定要在启动Docker之前关闭防火墙,你一定要在启动Docker之前关闭防火墙。

参考资料

Docker Network CLI

Docker Networking overview


版权声明:

原创不易,洗文可耻。除非注明,本博文章均为原创,转载请以链接形式标明本文地址。

你可能感兴趣的:(Docker,网络,docker,运维)