为什么Docker运行这么多进程来将端口映射到我的应用程序? [英] Why does Docker run so many processes to map ports though to my application?

查看:129
本文介绍了为什么Docker运行这么多进程来将端口映射到我的应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在容器中运行的应用程序,需要将一系列端口映射到该容器。

I have an application that runs in a container that requires a range of ports to be mapped to it.

docker run -p 2000-3000:2000-3000 myapp

当我运行此docker命令时,我的开发虚拟机停止运行。

When I run this docker command my development vm grinds to a halt.

然后查看进程,每个端口都有一个 docker-proxy

Then looking at the processes, there is a docker-proxy running for every port

$ ps -ef 
...
root     19796  7835  0 03:31 ?        00:00:00 docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 4000 -container-ip 172.17.0.4 -container-port 3000
root     19804  7835  0 03:31 ?        00:00:00 docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3999 -container-ip 172.17.0.4 -container-port 2999
root     19812  7835  0 03:31 ?        00:00:00 docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3998 -container-ip 172.17.0.4 -container-port 2998
...

$ ps -ef | grep -c docker-proxy
1003

它们都是docker守护进程的子代

They are all children of the docker daemon

root@default-docker:~# pstree -p
init(1)-+-VBoxService(1251)
        |-acpid(1277)
        |-crond(1235)
        |-docker(7835)-+-docker-containe(7841)-+-docker-containe(8031)---gitlab-ci-multi(8048)
        |              |                       |-docker-containe(9678)---mysqld(9693)
        |              |                       `-docker-containe(20577)---registry(20591)
        |              |-exe(19796)
        |              |-exe(19804)
        |              |-exe(19812)

每个进程都使用一块私有内存( / proc / $ pid / smaps )中的Pss

Each process uses a chunk of private memory (Pss in /proc/$pid/smaps)

$ for pid in $(pgrep exe); do printf "pid:%5s mem:%5s\n" $pid $(awk '/^Pss:/{t=t+$2}END{print t}' /proc/$pid/smaps); done
...
pid:28534 mem: 4011
pid:28543 mem: 3817
pid:28552 mem: 4001

每个端口都有DNAT规则,这是我期望在具有专用网络的Linux主机上完成此操作的方式。

There are also DNAT rules in place for each port, which is how I would have expected this to be done on a Linux host with private networks.

root@default-docker:~# iptables -t nat -vnL DOCKER
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
...
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:4000 to:172.17.0.4:3000
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3999 to:172.17.0.4:2999
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:3998 to:172.17.0.4:2998
...

为什么Docker每个端口启动一个进程?

为什么每个进程都需要4-6MB的内存?

为什么Docker在以下位置使用用户空间进程

Why is Docker launching a process per port?
Why does each process need 4-6MB of memory?
Why is Docker using a user space process at all?

推荐答案

为什么Docker完全使用用户空间进程?



奈杰尔·布朗(Nigel Brown)在码头工人代理,其中说明了操作方式和原因。

Why is Docker using a user space process at all?

Nigel Brown has written a detailed article on The docker-proxy which explains the how and why.


然后, docker-proxy 是一种全部捕获方法允许容器
端口转发到Docker主机。但是,通常认为
docker-proxy 的一种不错的解决方案,可以解决上面突出显示的
问题,并且当有大量的集装箱港口
暴露在外,它消耗大量内存。先前曾尝试
删除 docker-proxy 的依赖关系,但这与RHEL 6中老化的内核的限制相抵触
.x和CentOS 6.x,
,Docker项目感到有义务提供支持。因此,在当前版本1.5之前的所有Docker版本中,
docker-proxy 仍然是Docker体验
的主要组成部分。在我写这篇文章时,
版本1.6即将发布,并且已经有
删除了 docker-proxy 的自动要求。我将在另一篇文章中介绍

The docker-proxy, then, is a 'catch all' method for allowing container port forwarding to the Docker host. However, it's generally considered that the docker-proxy is an inelegant solution to the problems highlighted above, and when a large range of container ports are exposed, it consumes considerable memory. An attempt was previously made to remove the dependency for the docker-proxy, but this fell foul of the limitations of the aged kernel in RHEL 6.x and CentOS 6.x, which the Docker project feels duty bound to support. Hence, the docker-proxy remains a major constituent part of the Docker experience in all Docker versions up to the current version 1.5. As I write, version 1.6 is due for imminent release, and there have been moves to remove the automatic requirement for the docker-proxy, which I'll cover in another article.

Docker现在包括使用-userland-proxy = false 。这是在v1.7中引入的。

Docker now includes a daemon run time option to disable the userland proxy with --userland-proxy=false. This was introduced in v1.7.

似乎有一个很少边缘情况错误 = https://github.com/docker/docker/issues/21860 rel = nofollow noreferrer>存在,当禁用用户级代理时。还有 IPV6问题

There seems to be a few edge case bugs that exist when disabling the userland proxy. There are also IPV6 issues

存在一个开放的GitHub问题,默认情况下禁用用户名代理(RHEL6是不再受Docker支持)。

There is an open GitHub issue for disabling the userland proxy by default (RHEL6 is no longer supported by Docker).

似乎没有原因除了以这种方式实施之外。单个进程应该能够处理容器的所有端口映射

There doesn't appear to be a reason for this other than it was implemented this way. A single process should be capable of handling all of the port mappings for a container

代理实现程序包看起来很干净,并在内置的Go功能中使用,因此这可能只是Go的初始垃圾收集限制,使其可以增长到〜5MB。

The proxy implementation and package looks clean and uses in built Go functionality so this might just be Go's initial garbage collection limits that allow it to grow to ~ 5MB.

编辑:内存使用量已在Docker 1.12中得到有所改进 。每个端口仍然有一个进程,但是每个进程现在仅使用约750k的私有内存空间。

EDIT: Memory usage has been improved in Docker 1.12. There is still a process per port but each process now only uses ~ 750k of private memory space.

这篇关于为什么Docker运行这么多进程来将端口映射到我的应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆