当前位置: 首页 > news >正文

解密 docker 容器内 DNS 解析原理

背景

这几天在使用 docker 中,碰到了在容器中 DNS 解析的一些问题。故花些时间弄清了原理,写此文章分享。

1. docker run 命令启动的容器

以启动一个 busybox 容器为例:

root@ubuntu20:~# docker run -itd --name u1 busybox
63b59ca8aeac18a09b63aaf4a14dc80895d6de293017d01786cac98cccda62ae
root@ubuntu20:~# docker exec -it u1 sh
/ # 
/ # ping www.baidu.com
PING www.baidu.com (14.119.104.189): 56 data bytes
64 bytes from 14.119.104.189: seq=0 ttl=127 time=34.976 ms
64 bytes from 14.119.104.189: seq=1 ttl=127 time=35.369 ms
^C
--- www.baidu.com ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 34.976/35.172/35.369 ms

在容器里可以 ping 通外部的域名。

过程

查看容器中的 /etc/resolv.conf 文件内容:

/ # cat /etc/resolv.conf 
# This file is managed by man:systemd-resolved(8). Do not edit.
#
# This is a dynamic resolv.conf file for connecting local clients directly to
# all known uplink DNS servers. This file lists all configured search domains.
#
# Third party programs must not access this file directly, but only through the
# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,
# replace this symlink by a static file or a different symlink.
#
# See man:systemd-resolved.service(8) for details about the supported modes of
# operation for /etc/resolv.conf.nameserver 192.168.30.2
search localdomain

使用的 DNS 服务器 ip 是 192.168.30.2。

这正是宿主机【我使用的是 Ubuntu 20.04 虚拟机】使用的 DNS 服务器ip地址。在宿主机上使用 systemd-resolve --status 命令可以看到:

root@ubuntu20:~# systemd-resolve --status
....Link 2 (ens33)Current Scopes: DNS         
DefaultRoute setting: yes         LLMNR setting: yes         
MulticastDNS setting: no          DNSOverTLS setting: no          DNSSEC setting: no          DNSSEC supported: no          Current DNS Server: 192.168.30.2DNS Servers: 192.168.30.2DNS Domain: localdomain ...

结论

以这种方式启动的容器,容器内部的 /etc/resolv.conf 文件中配置的 ip 是宿主机使用的 DNS 服务器ip。

参考文章:How does the Docker DNS work?

2. docker compose 启动的容器

在使用 docker compose 时,我们知道,一个容器可以使用另一个容器的服务名来获取它的ip地址。

看个例子,docker-compose.yml 文件内容如下:

version: '2'services:redis:image: redis:3.2busybox:image: busyboxstdin_open: truetty: true

它定义了两个服务 redis 和 busybox。

进入 busybox 容器内,可以使用 “redis”来获取 redis 容器的 ip 地址:

root@ubuntu20:~/test# docker-compose up -d
Creating network "test_default" with the default driver
Creating test_redis_1   ... done
Creating test_busybox_1 ... done
root@ubuntu20:~/test# docker-compose psName                   Command               State    Ports  
------------------------------------------------------------------
test_busybox_1   sh                               Up              
test_redis_1     docker-entrypoint.sh redis ...   Up      6379/tcproot@ubuntu20:~/test# docker exec -it test_busybox_1 sh
/ # 
/ # ping redis -c 1
PING redis (192.168.112.2): 56 data bytes
64 bytes from 192.168.112.2: seq=0 ttl=64 time=1.103 ms--- redis ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 1.103/1.103/1.103 ms

反之亦然。这是怎么做到的呢?

过程

先看看容器中的 /etc/resolv.conf 文件:

/ # cat /etc/resolv.conf 
search localdomain
nameserver 127.0.0.11
options edns0 trust-ad ndots:0

它使用的 DNS 服务器 ip 地址居然是个环回地址 127.0.0.11 !那是怎么做到可以解析域名的呢?

在容器内的环回口抓下包看下:

root@ubuntu20:~/test# docker inspect test_busybox_1 | grep Pid"Pid": 211432,"PidMode": "","PidsLimit": null,
root@ubuntu20:~/test# nsenter -t 211432 -n tcpdump -i lo -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
10:11:39.223669 IP 127.0.0.1.58808 > 127.0.0.11.59712: UDP, length 34
10:11:39.223707 IP 127.0.0.1.58808 > 127.0.0.11.59712: UDP, length 34
10:11:39.224305 IP 127.0.0.11.53 > 127.0.0.1.58808: 6751 0/0/0 (23)
10:11:39.224682 IP 127.0.0.11.53 > 127.0.0.1.58808: 18524 1/0/0 A 192.168.112.2 (44)

这里有个小技巧:因为 busybox 容器中并没有 tcpdump 程序,所以使用 nsenter 进入了容器的网络命名空间,执行抓包程序。

通过抓包可以看到:DNS 请求被发给了 127.0.0.11.59712 ?说明有某个服务监听这个 ip地址+端口。
使用 ss 命令查看下:

root@ubuntu20:~/test# nsenter -t 211432 -n ss -unlp
State              Recv-Q             Send-Q                          Local Address:Port                            Peer Address:Port             Process             
UNCONN             0                  0                                  127.0.0.11:59712                                0.0.0.0:*                 users:(("dockerd",pid=1078,fd=78))

发现监听这个 ip 地址加端口的居然是 dockerd 程序!原来 DNS 请求是发送给了 dockerd 程序处理了!

但是 DNS 请求目的端口不是 53 吗?怎么变成了这个 59712,这是怎么回事?看下 iptables nat 表:

root@ubuntu20:~/test# nsenter -t 211432 -n iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER_OUTPUT
-N DOCKER_POSTROUTING
-A OUTPUT -d 127.0.0.11/32 -j DOCKER_OUTPUT
-A POSTROUTING -d 127.0.0.11/32 -j DOCKER_POSTROUTING
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p tcp -m tcp --dport 53 -j DNAT --to-destination 127.0.0.11:43107
-A DOCKER_OUTPUT -d 127.0.0.11/32 -p udp -m udp --dport 53 -j DNAT --to-destination 127.0.0.11:59712
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p tcp -m tcp --sport 43107 -j SNAT --to-source :53
-A DOCKER_POSTROUTING -s 127.0.0.11/32 -p udp -m udp --sport 59712 -j SNAT --to-source :53

原来有一条 DNAT 规则,将目的 ip 为127.0.0.11,端口为 53 的 udp 数据包,目的端口修改为 59712。一切真相大白!

结论

以 docker compose 启动的容器,使用的 DNS 服务器是 dockerd 程序内部的 DNS 服务器。

它是通过以下三步来实现的:

  1. dockerd 在容器的网络命名空间中创建一个监听 127.0.0.11 的 udp socket
  2. 设置容器内 /etc/resolv.conf 文件ip 为 127.0.0.11
  3. 容器内添加 iptable DNAT 规则

相关文章:

解密 docker 容器内 DNS 解析原理

背景 这几天在使用 docker 中,碰到了在容器中 DNS 解析的一些问题。故花些时间弄清了原理,写此文章分享。 1. docker run 命令启动的容器 以启动一个 busybox 容器为例: rootubuntu20:~# docker run -itd --name u1 busybox 63b59ca8aeac…...

故障诊断模型 | Maltab实现SVM支持向量机的故障诊断

效果一览 文章概述 故障诊断模型 | Maltab实现SVM支持向量机的故障诊断 模型描述 Chinese: Options:可用的选项即表示的涵义如下   -s svm类型:SVM设置类型(默认0)   0 – C-SVC   1 --v-SVC   2 – 一类SVM   3 – e -SVR   4 – v-SVR   -t 核函数类型:核函…...

开源的网站数据分析统计平台——Matomo

Matomo 文章目录 Matomo前言一、环境准备1. 整体安装流程2.安装PHP 7.3.303.nginx配置4.安装matomo4.1 访问安装页面 http://192.168.10.45:8088/index.php4.2 连接数据库4.3 设置管理员账号4.4 生成js跟踪代码4.5 安装完成4.6 警告修改4.7 刷新页面,就可以看到登陆…...

linux入门到地狱

linux—001入门 IT圈必备(前端工作者用的比较少) 老旧电脑跑linux不容易卡 我代码没保存windows闪退,僵停(vs2019卡掉线),重启更新,占用cpu内存服务报错pip各种bug 出来生态环境友好其他的全是bug(bug时间成本超过了windows快捷友好生态) 那就说明wind…...

架构”4+1“视图

1995年Kruchten提出了著名的“41”视图,用来描述软件系统的架构。在“41”视图中,(物理视图 )用来描述系统软硬件之间的映射关系,这个视图往往(系统工程人员)最为关注;(逻…...

『精』Vue 组件如何模块化抽离Props

『精』Vue 组件如何模块化抽离Props 文章目录 『精』Vue 组件如何模块化抽离Props一、为什么要抽离Props二、选项式API方式抽离三、组合式API方式抽离3.1 TypeScript类型方式3.2 文件分离方式3.3 对文件分离方式优化 参考资料💘推荐博文🍗 一、为什么要抽…...

JavaScript字符串字面量详细解析与代码实例

JavaScript字符串字面量是一种表示字符串值的语法结构,通常用双引号或单引号括起来。 var str1 "Hello World!"; var str2 Hello World!;另外,如果需要在字符串中包含双引号或单引号,可以使用转义字符\来实现。 var str3 &quo…...

Android java Handler sendMessage使用Parcelable传递实例化对象,我这里传递Bitmap 图片数据

一、Bundle给我们提供了一个putParcelable(key,value)的方法。专门用于传递实例化对象。 二、我这里传递Bitmap 图片数据,实际使用可以成功传统图像数据。 发送:Bundle bundle new Bundle();bundle.putParcelable("bitmap",bitmap);msg.setD…...

CTF工具PDF隐写神器wbStego4open安装和详细使用方法

wbStego4open安装和详细使用方法 1.wbStego4open介绍:2.wbStego4open下载:3.wbStego4open原理图:4.wbStego4open使用教程:第一步:第二步:第三步:第四步:第五步: 5.wbSteg…...

docker镜像使用

一、查看docker版本 docker version docker默认安装目录 /var/lib/docker 目录文件如下: 二、查看下载的镜像 docker images 三、下载镜像 docker pull [OPTIONS] NAME[:TAG|DIGEST] option作用-a, --all-tags拉取所有 tagged 镜像–disable-content-trust…...

【Git】git的下载安装与使用

目录 目录 一.下载安装 官方下载 淘宝镜像下载 安装 二.创建本地仓库 三.git的基本操作命令 git status git add . git commit -m " " 四.gitee(码云)的使用 配置ssh公钥 ​编辑 查看公钥 gitee创建仓库 将本地仓库的文件上传到远程仓库…...

R语言中的函数27:polynom::polynomial(), deriv(),integral(),solve()多式处理函数

文章目录 介绍polynomial()用法参数实例多项式的加减乘除等运算实例 deriv()和integral()用法参数实例solve()参数实例 介绍 R语言中的polynom包可以实现对多项式的操作,例如:加、减、乘、除、微分、积分。使用的时候先用polynomial()函数定义一个多项式…...

基于STM32CubeMX和keil采用USART/UART实现非中断以及中断方式数据回环测试借助CH340以及XCOM

文章目录 前言1. 接口概述1.1 USART/UART接口1.2 串口通信参数1.3 波特率计算 2. 传输函数3. 回环测试3.1 上位机环境配置3.2 阻塞模式3.3 中断模式 4. STM32CubeMX配置4.1 时钟配置4.2 调试配置4.3 串口引脚配置4.4 工程配置 5. 测试效果6. 不借助上位机回环测试总结 前言 这…...

Spring cloud负载均衡 @LoadBalanced注解原理

接上一篇文章,案例代码也在上一篇文章的基础上。 在上一篇文章的案例中,我们创建了作为Eureka server的Eureka注册中心服务、作为Eureka client的userservice、orderservice。 orderservice引入RestTemplate,加入了LoadBalanced注解&#x…...

C#when关键字

在C#中,when关键字用于在模式匹配表达式中添加条件。它允许您在模式匹配的过程中指定额外的条件,以进一步过滤匹配的模式。当模式匹配和附加条件都为真时,相关的代码块将被执行。 以下是when关键字的详细解释以及示例说明: 语法…...

华为政企无线局域网产品集

产品类型产品型号产品说明 室内接入点AirEngine 5760-51AirEngine 5760-51是华为发布的支持Wi-Fi 6(802.11ax)标准的新一代室内AP,适合部署在企业办公、零售、制造等场景。 通过软件定义射频,能够在双频、三频模式灵活切换&a…...

解释 RESTful API

RESTful API是一种基于HTTP协议的API设计风格,它的核心思想是将每个资源(如用户、订单等)抽象成一个URI(统一资源标识符),通过HTTP协议定义的方法(如GET、POST、PUT、DELETE等)对资源…...

青翼科技-国产化ARM系列TES720D-KIT

板卡概述 TES720D-KIT是专门针对我司TES720D(基于复旦微FMQL20S400的全国产化ARM核心板)的一套开发套件,它包含1个TES720D核心板,加上一个TES720D-EXT扩展底板。 FMQL20S400是复旦微电子研制的全可编程融合芯片,在单…...

Tomcat为什么支持线程池?

Tomcat作为一个Java Servlet容器,支持线程池是因为它能够处理多个并发请求。这些请求可以是对Web应用程序的HTTP请求、Servlet的请求,或其他支持的协议。 支持线程池的主要原因包括: 并发处理能力: 提高性能: 使用线程…...

Mac安装VMware

去官网下载一下VMware Download VMware Fusion | VMware | SG 下载完成之后,打开直接闪退,参考这篇文章解决 解决macOS13安装Fusion13闪退的问题-CSDN博客 然后即可成功顺行...

项目部署文档

申请SSL证书 先申请,用免费的 下载证书 先将下载下来的保存起来 服务器安装JDK: 创建develop目录 mkdir /usr/local/develop/ 把JDK压缩包上传到/usr/local/develop/目录 解压安装包 并且将安装到指定目录 tar -zxvf /usr/local/develop/jdk-8u191-linux-x64.tar.gz -C /us…...

HTML+CSS阶段知识点梳理

目录 一、简单的网页结构 二、常用标签 三、列表 四、CSS引入方式 五、常用选择器 1、标签(元素)选择器 2、id选择器 3、class选择器 4、通配选择器 5、复合选择器 6、关系选择器 7、属性选择器 8、伪类选择器 9、a元素的伪类 10、伪元素…...

网易按照作者批量采集新闻资讯软件说明文档

大家好,我是淘小白~ 今天给大家介绍的爬虫软件是网易按照作者采集的软件 1、软件语言: Python 2、使用到的工具 Python selenium库、谷歌浏览器、谷歌浏览器驱动 3、文件说明: 4、配置文件说明: 5、环境配置 安装Python&am…...

SwiftUI 代码调试之都是“变心”惹的祸

0. 概览 这是一段非常简单的 SwiftUI 代码,我们将 Item 数组传递到子视图并在子视图中对其进行修改,修改的结果会立即在主视图中反映出来。 不幸的是,当我们修改 Item 名称时却发现不能连续输入:每次敲一个字符键盘都会立即收起并…...

u20.04安装slam库

git clone https://github.com/strasdat/Sophus.git // 下载的最新版是模板类的 git checkout a621ff // 切换为非模板类的历史版本 模板类Sophus的依赖库是Eigen(版本为3.3.X)和fmt,需提前安装好Eigen库和fmt库 git clone https://github.c…...

齐纳二极管,肖特基二极管,瞬态电压抑制二极管

普通二极管,齐纳二极管,肖特基二极管的符号: 瞬态电压抑制(TVS)二极管是一种特殊的齐纳二极管,其符号如下: 普通二极管 普通二极管由n类型 的半导体和p类型的半导体结合而成。 硅材料制成的二…...

axios 全局错误处理和请求取消

这两个功能都是用拦截器实现。 前景提要: ts 简易封装 axios,统一 API 实现在 config 中配置开关拦截器 全局错误处理 在构造函数中,添加一个响应拦截器即可。在构造函数中注册拦截器的好处是,无论怎么实例化封装类&#xff0c…...

无法加载文件 C:\Program Files\nodejs\cnpm.ps1,因为在此系统上禁止运行脚本。有

cnpm : 无法加载文件 C:\Program Files\nodejs\cnpm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Poli cies。 所在位置 行:1 字符: 1 cnpm run debug ~~~~ Categ…...

学电脑编程零基础,计算机编程入门先学什么

学电脑编程零基础,计算机编程入门先学什么,建议先从容易学习的语言入手,比如中文编程。 给大家分享一款中文编程工具,零基础轻松学编程,不需英语基础,编程工具可下载。 这款工具不但可以连接部分硬件&…...

SQL左连接实战案例

要求:用表df1和表df2的数据,得到df3 一、创建表 CREATE TABLE df1 (姓名 varchar(255) DEFAULT NULL,年龄 int DEFAULT NULL,部门 varchar(255) DEFAULT NULL,id int DEFAULT NULL );CREATE TABLE df2 (部门 varchar(255) DEFAULT NULL,年龄 int DEFAU…...