docker proxy实现原理解析

 更新时间:2026年04月22日 10:15:55   作者:janeysj  
Docker 是一个开源的容器化平台,它允许开发者打包、分发和运行应用程序,本文给大家介绍docker proxy实现原理,感兴趣的朋友跟随小编一起看看吧

docker-proxy 是 Docker 网络架构中的一个“传声筒”。当你启动一个容器并使用 -p 参数映射端口时,它就在幕后默默工作。如下的一个docker-compose配置:

注意这里的端口映射,就类似于你运行 docker run -p 30003:30003 的命令时,你实际上是要求宿主机将发往 30003 端口的流量转发到容器内部的 30003 端口。

为了实现这个转发,Docker 使用了两种机制:

  • DNAT (iptables 规则): 这是主要方式,效率极高,直接在内核层面处理流量。
  • docker-proxy: 这是一个运行在用户态(Userland)的小程序。每当你映射一个端口,Docker 就会为该端口启动一个独立的 docker-proxy 进程。

以上两个动作是由docker自动完成的,这时,你使用如下命令(netstat, ps)可以查看到该docker-proxy进程:

但是,如果你使用命令sudo kill -9 2152 把这个docker-proxy进程杀死,你再次访问该主机的30003端口,仍然可以正常访问!!!但是你ssnetstat搜索不到任何关于30003端口的信息。

1. 为什么进程杀了,网页还能访问?

这就是 Docker 的“双保险”机制:

  • 保险 A (iptables): 只要容器还在运行,Docker 就会在 Linux 内核中写入一条 iptables 转发规则(DNAT)。这条规则在内核态生效,不依赖任何进程
  • 保险 B (docker-proxy): 这是一个用户态进程,主要负责处理一些 iptables 覆盖不到的边角情况。

当你杀掉 docker-proxy 进程后,内核态的 iptables 规则依然稳如泰山。所以,外部流量打到 30003 时,内核直接把包转给了容器,网页自然能打开。这时你输入命令,大概率会看到:

[root@localhost ~]#  sudo iptables -t nat -L DOCKER -n | grep 30003
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:30003 to:172.21.0.3:30003

2. 为什么ss搜不到了?

ssnetstat 查的是系统中的 Socket 监听表

  • docker-proxy 运行时,它会占用(Bind)30003 端口,ss 就能看到它。
  • 你把它杀了,这个端口在用户态就处于“空闲”状态。
  • 但是,内核 iptables 就像一个“隐形拦截者”,它在数据包还没到达 Socket 层之前就把包抢走了。

3. 会有什么后果?

虽然现在访问正常,但杀掉 docker-proxy 可能会导致以下小问题:

  • 宿主机局部回环失效: 在某些配置下,你在宿主机本地执行 curl localhost:30003 可能会失败(尽管从外网访问是好的)。
  • 状态不一致: Docker 此时并不知道你手动杀了它的组件。当你下次 docker stoprm 这个容器时,Docker 可能会因为找不到该进程而报一个小错误(尽管它通常会自动忽略)。

4. 怎么恢复?

如果你想让 docker-proxy 重新出现,最简单的方法是重启容器

docker restart web-ui

重启后,Docker 会重新创建 iptables 规则并启动一个新的 docker-proxy 进程。

总结:

一个很重要的结论:Docker 的端口映射本质上是内核行为(iptables),docker-proxy 只是一个辅助。 只要内核规则在,服务就不会断。

到此这篇关于docker proxy实现原理解析的文章就介绍到这了,更多相关docker proxy原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • docker imageid 和 digest区别解析

    docker imageid 和 digest区别解析

    在Docker中,image ID和digest是两个不同的标识符,用于唯一标识和引用Docker镜像的不同方面,这篇文章主要介绍了docker imageid 和 digest区别,需要的朋友可以参考下
    2023-06-06
  • Docker如何给Springboot项目动态传参的实现方法

    Docker如何给Springboot项目动态传参的实现方法

    这篇文章主要介绍了Docker如何给Springboot项目动态传参的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • keepalived+nginx+httpd实现的双机热备+负载均衡

    keepalived+nginx+httpd实现的双机热备+负载均衡

    本文主要介绍了keepalived + nginx + httpd 实现的双机热备+负载均衡,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-07-07
  • docker创建redis镜像的方法

    docker创建redis镜像的方法

    本篇文章主要介绍了docker创建redis镜像的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • docker容器指定主机同网段方式

    docker容器指定主机同网段方式

    文章介绍了如何使用Docker的macvlan网络模式,让容器直接连接到物理网络,提高网络性能和稳定性,同时,也提供了创建、绑定、配置和解除容器网络的相关命令
    2025-12-12
  • docker从Path值看容器启动命令方式

    docker从Path值看容器启动命令方式

    Docker容器的config.v2.json文件中的Path字段指定了容器启动时要执行的主程序(可执行文件)的路径,决定了容器运行时的入口点,它通常是容器文件系统中某个可执行文件的绝对路径
    2026-02-02
  • docker-compose中变量的使用方式

    docker-compose中变量的使用方式

    这篇文章主要介绍了docker-compose中变量的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Docker镜像构建-Aliyun详解

    Docker镜像构建-Aliyun详解

    这篇文章主要介绍了Docker镜像构建-Aliyun的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-07-07
  • Docker服务器存储资源池不足的问题解决

    Docker服务器存储资源池不足的问题解决

    这篇文章主要给大家介绍了关于Docker服务器存储资源池不足的问题解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • k8s和Docker关系简单说明

    k8s和Docker关系简单说明

    这篇文章主要介绍了k8s和Docker关系简单说明,本文利于图文讲解的很透彻,有需要的同学可以研究下
    2021-03-03

最新评论