前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Docker入门——网络相关

Docker入门——网络相关

原创
作者头像
cocoon_yh
发布于 2019-09-09 13:04:40
发布于 2019-09-09 13:04:40
1.4K0
举报

背景

某次在试图从容器内访问到本地的数据库时,发现在本机上并没有 docker0 这个网桥。学习了一波 Docker 网络相关的知识后作出了以下总结。

相信下面这张图大家没少看过,Docker 相较于 VM 更加轻量,不需要虚拟出自己的操作系统层,具有更多的优点。

docker.png
docker.png

上图来源于网络,后文中也将对来源于网络的图做出说明

然而笔者想当然的就以为 Docker 在所有系统下都是这种架构。查阅相关资料后发现,Dockerlinux 环境下确实是这样运行的,但是在 WindowsmacOS 系统下,Docker 会先启一个 VM ,然后在该 VM 上运行 Docker 环境。新版的 Docker for Mac 已经不再使用 VirtualBox 提供虚拟机环境,而是使用更轻量的 HyperKit ,设计上更为巧妙,本文就不展开讲这个点了。下图是 Docker for Mac 的架构图。

-1.png
-1.png

因此 docker0 网桥是在虚拟机内,而不是在宿主机内。可想而知,运行在虚拟机中与运行在本机上肯定是有区别的,因此 Docker for Mac 实际上自带了 k8s 环境,并且通过端口转发到宿主机,以屏蔽用户对 VM 的感知。然而要实现容器到宿主机的通信,还需要进行另一番调研。

下面先介绍一下 Docker 支持的几种网络模式。

Docker 支持的网络模式

Network

Description

none

no networking in the container

bridge

Connect the container to the bridge via veth interfaces

host

Use the host's network stack inside the container

Container:<name\id>

Use the network stack of another container, specified via its name or id

Network

Connects the container to a user created network(using docker network create command)

NETWORK: NONE

这种网络模式下无法联网,仅有一个 loopback 回环网络,没有其他网卡。这种类型的网络无法联网,但可以通过 link 容器来实现容器间通信,这种网络模式可以很好的保证容器的安全性。同时,这种网络模式下用户自己自行创建网络,可以实现更为灵活复杂的网络。

0.png
0.png

NETWORK: BRIDGE

这是容器默认的网络模式。桥接模式会为 Docker Container 创建独立的网络堆栈,保证容器内的进程组使用独立的网络环境,从而实现容器间、容器与宿主机之间的网络栈隔离。同时,桥接模式可以通过宿主机上的 docker0 网桥来实现宿主机与容器之间的网络通信。

桥接模式会在主机上创建两个虚拟网络接口设备,一个附加在宿主机上的 docker0 网桥内,并命名为 veth0 ,另一个附加在 Docker Container 所属的 namespace 的下,并命名为 eth0

1.png
1.png

通过 veth pair 技术,其特性可以保证无论哪一个 veth 接收到网络报文,都会将报文传输给另一方,这就实现了从容器到宿主机的网络连通性。然而上面也提到了 Docker 需要运行在 linux 环境下,所以我们无法在主机上看到 docker0 网桥,这个网桥位于虚拟机中。

NETWORK: HOST

这种网络模式下容器将跟主机共享网络堆栈,因此容器可以直接使用宿主机的 eh0 实现与外界的通信,并且主机所有的接口都可以被容器访问及使用。

host.png
host.png

在这种模式下,容器将获取更高的网络性能,因为它使用主机的网络栈,不需要通过 Docker 守护进程进行一层虚拟化。但是,这种模式也会导致容器网络环境隔离性弱化,即容器不再拥有隔离的、独立的网络栈。容器会与宿主机竞争网络栈的使用,同时容器也不再拥有所有的端口资源,因为部分端口已经被宿主机本身的服务占用,还有部分端口用于桥接模式容器的端口映射。

NETWORK: CONTAINER

这种网络模式下,容器将和另一个容器共享网络堆栈,因此,同样需要注意端口冲突等问题。该模式下,两个容器与其他容器以及宿主机之间存在网络隔离。

container.png
container.png

USER-DEFINED NETWORK

开发者可以使用 Docker 网络驱动程序或者外部的网络驱动程序来创建网络,也可以把多个容器连接到同一个网络下。在这里不展开介绍。

解决方法

方案一(仅在 macOS/Windows 下可用)

Docker 本身针对这种场景已经提出了一些解决方案。从版本 18.03 开始,Docker for Mac 提供一个特殊的 DNS name 以便用户从容器内访问到本机, 这个 DNS name 被解析至主机在 docker 内使用的内部 IP 。同时其他版本的 Docker Desktop for Mac 也有对应的 host ,如下所示:

  • Docker for Mac v 18.03 and above
  • host.docker.internal
  • Docker for Mac v 17.12 to v 18.02
  • docker.for.mac.host.internal
  • Docker for Mac v 17.06 to v 17.11
  • docker.for.mac.localhost
  • Docker for Mac 17.05 and below
  • Docker 不提供,需要自己进行配置,具体配置方法可以参考 Janne Annala 的回答
代码语言:txt
AI代码解释
复制
https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach
1的副本.png
1的副本.png

如上图所示,可以通过 host.docker.internal 直接访问到宿主机内的服务

方案二(仅在 Linux 下可用)

使用桥接模式。

可以看到宿主机下已经有了 docker0 网桥,且地址为 172.17.0.1

2.png
2.png

进入容器并查看容器内的网络接口信息和路由表可以发现 eth0 和宿主机中 docker0 的网段相同,且已经将 docker0 的接口地址设置为了默认网关,即匹配到的请求将通过 172.17.0.1 转发到目标地址。

3.png
3.png

那么通过该地址即可实现从容器到宿主机的访问。

4.png
4.png

方案三(仅在 Linux 下可用)

使用 host 模式启动服务就可以直接访问本机上的服务。利弊如上所述,若在生产环境使用该模式还需要自己再多做相关调研。

5.png
5.png

延展阅读

读到这的读者可能就会想,那容器内部需要访问外界,或者外界需要访问服务内部该咋办?好像刚刚提到的知识点不足以支撑这一流程呀?docker0 网段和宿主机的网段不同,外界无法得知容器 IP 更无法直接访问到容器内部。

6.png
6.png

这里就要引入另一个概念 NAT(Network Address Translation) ,是一种用于重写源IP地址或目的IP地址的技术。

外界访问容器内部

前提条件:容器运行时通过 -P 或 -p 指令主动暴露端口并将端口映射至主机上

to_docker.png
to_docker.png
  1. 外界直接请求 host_ip:port_0
  2. 通过 DNAT 将请求的目的地址修改为 container_ip:port_1
  3. 宿主机将请求转发给 veth pair
  4. veth pair 将请求通过 veth 转发至容器内部的 eth0
  5. 回包时也通过 docker0 转发至宿主机的 eth0 发送回包

通过检测数据包可以看到请求的目的 IP 被修改为了对应的容器 IP ,以完成外界对容器内部的访问

7.png
7.png
8.png
8.png

容器内部访问外界

from_docker.png
from_docker.png
  1. 容器内发出请求,此时会随机选取一个未被占用的端口 port0 作为源端口
  2. 请求通过 eth0 转发至 docker0 网桥处的 veth
  3. docker0 网球将请求转发至宿主机的 eth0
  4. 宿主机处理请求时通过 SNAT 将请求源地址修改为 host_ip:port_1 并转发出去
  5. 外界回包时发送至宿主机的 eth0
  6. 按照 iptables 规则,宿主机将请求转发至容器内部

查看 iptables 规则可知,从 172.17.0.0 网段出去访问外网的请求都会交由 MASQUERADE 处理。而 MASQUERADE 的处理就是将请求的源 ip 替换成宿主机的 ip 并发出去,也就是做了一次 NAT 处理。

9.png
9.png
通过检测数据包可知,请求的源 ip 确实被从 docker0 网段的容器 ip:172.17.0.2 修改为 eth1:10.12.91.17
10.png
10.png
11.png
11.png

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
解密Docker容器网络
一个Linux容器能看见的“网络栈”,被隔离在它自己的Network Namespace中。
JavaEdge
2023/07/09
3600
解密Docker容器网络
docker网络
我们在使用 docker run 创建 Docker 容器时,可以用--net 选项指定容器的网络模式,Docker 有以下 4 种网络模式:
cuijianzhe
2022/06/14
6610
docker网络
Docker容器学习梳理--容器间网络通信设置(Pipework和Open vSwitch)
自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求。容器的网络通信又可以分为两大方面:单主机容器上的相互通信,和跨主机的容器相互通信。下面将分别针对这两方面,对容器的通信原理进行简单的分析,帮助大家更好地使用docker。前面已经在Docker容器学习梳理--基础知识(2)这一篇中详细介绍了Docker的网络配置以及pipework工具。 docker单主机容器通信 基于对net namespace的控制,docker可以为在容器创建隔离的网络环境,在隔离的网络环境下,
洗尽了浮华
2018/01/23
3.5K0
Docker容器学习梳理--容器间网络通信设置(Pipework和Open vSwitch)
浅谈容器网络
容器技术通过轻量化的资源隔离机制,极大地简化了应用部署的复杂性。而容器网络作为容器生态的核心组件,直接影响着容器间通信、服务发现及跨主机协同的能力。本文将从容器网络的基础组件出发,逐步剖析其工作原理及关键实现。
rxg456
2025/04/01
820
浅谈容器网络
docker复制文件到宿主机_下面哪几个属于docker网络模式
此种方式是将容器的某个端口映射到宿主机的某个端口,其它主机访问容器提供的服务需要通过宿主机的IP进行访问:
全栈程序员站长
2022/09/25
8170
docker复制文件到宿主机_下面哪几个属于docker网络模式
【重识云原生】第六章容器6.1.12节——Docker网络模型设计
        先来简要回顾一下前面的内容,namespace和cgroup是Linux 内核的两大特性,namespace的诞生据说就是为了支持容器技术,那么这俩特性到底干了啥呢?
江中散人_Jun
2022/09/28
4660
【重识云原生】第六章容器6.1.12节——Docker网络模型设计
深入解析容器网络
在使用kubernetes之前, 最为火热的技术就是Docker技术了。 它完成了从虚拟机时代的过度,是走向云原生时代的开端。 但是由于docker的故步自封导致被google的开源的kubernetes后来居上, 现在的Docker虽然在积极改进, 但是主流大势已经被kubernetes掌握, 所以也只能起到助力作用。 回归正题, 在kubernetes的服务发现, 服务网格等技术火热之前, 是怎么来实现容器之间的通信呢 ?本文我们就来探讨一下。
用户11097514
2024/08/05
1560
深入解析容器网络
Docker Network
docker 的网络驱动有很多种方式,docker 官网给出的网络解决方案有 6 种,分别是:bridge、host、overlay、macvlan、none、Network plugins。每个网络都有自己的特点,应用场景各不相同,例如当有多台主机上的 docker 容器需要容器间进行跨宿主机通讯时,overlay 和 macvlan 可提供解决方案,而默认 docker 采用的是 bridge 模式,此模式下不能与其他主机上的 docker 容器通讯。本篇主要关注 docker 单机通讯方式的几种通讯模式:bridge、host、none 和 container。
1ess
2021/11/01
6010
Docker Network
Docker容器中的应用是怎么跟外界通信的?
当你安装Docker时,它会自动创建三个网络,使用docker network ls命令可以列出这些网络:
Java学习录
2020/01/22
1.8K0
docker浅入深出4
带着我们就这些问题,我们来学习一下docker的网络模型,最后我会通过抓包的方式,给大家演示一下数据包在容器和宿主机之间的转换过程。
萧晚歌
2020/09/04
9530
docker浅入深出4
docker容器网络入门
尽管很多公司已经都使用k8s方便管理了各种容器应用,但作为一个容器管理者,需要了解其中网络如何运作,前面已经介绍了K8s中的网络,这里就来研究下docker容器中的网络配置。
希里安
2023/10/30
3270
docker容器网络入门
006.Docker网络管理
Docker使用Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。
木二
2019/07/26
1.1K0
Docker 网络模式详解及容器间网络通信
Docker本身在它创建之初,它就有自己的网络驱动器,叫Container Network Manager,简称CNM。本身这个CNM会支持多种模式,本节来看一看这些模式的区别,然后去了解一下,要让一个容器网络真正地配置好,让容器真正地模拟成一个虚拟机,我们最终要做哪些配置。
贾维斯Echo
2024/03/20
2.7K0
Docker 网络模式详解及容器间网络通信
docker容器单机网络
通过文章 容器的本质 (opens new window)可知,容器只是一个进程,而容器所能看到的网络栈,是隔离在自己的 Network Namespace (opens new window) 中。docker 容器单机网络支持四种网络模式,也都是基于 Network Namespace 实现的。本文主要是介绍这四种模式的使用方法及实现原理。
编程黑洞
2023/03/04
3670
docker容器单机网络
Docker网络
  Docker 服务默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),该桥接网络的名称为docker0,它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信。
别团等shy哥发育
2023/02/25
7030
Docker网络
大数据开发:Docker的四种网络模式详解
我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下4种网络模式:
成都加米谷大数据
2021/02/24
1.2K0
大数据开发:Docker的四种网络模式详解
Docker网络——实现容器间通信、容器与外网通信以及容器的跨主机访问
由上图我们可以看到创建的网络ID为4554d78082da ,使用ip addr查看本机网络:
1850810
2021/06/06
16.9K0
Docker 网络配置
(1)容器间、容器与主机间的互联和通信以及端口映射 (2)容器IP变动时候,可以通过服务名直接网络通信而不受到影响
为为为什么
2024/08/01
3200
《菜农升职记》之 Docker网络
“小菜农,这个测试环境的服务器连接信息,你登上去通过docker部署下你刚刚提交的分支测试下哈!”
蔡不菜丶
2022/09/21
3580
《菜农升职记》之 Docker网络
一文读懂 Kubernetes 容器网络
在Kubernetes中要保证容器之间网络互通,网络至关重要。而Kubernetes本身并没有自己实现容器网络,而是通过插件化的方式自由接入进来。在容器网络接入进来需要满足如下基本原则:
iMike
2021/02/07
6600
相关推荐
解密Docker容器网络
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档