我有一个在容器中运行的应用程序,需要将一系列端口映射到它。
docker run -p 2000-3000:2000-3000 myapp
当我运行这个docker命令时,我的开发vm会停止运行。
然后查看进程,每个端口都有docker-proxy
$ 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守护程序的孩子
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)
每个进程都使用一块私有内存(Pss
中的/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主机上完成此操作的方法。
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完全使用用户空间进程?
答案 0 :(得分:6)
Nigel Brown撰写了一篇关于The docker-proxy的详细文章,其中解释了如何以及为什么。
然后,
docker-proxy
是允许容器的“全部捕获”方法 端口转发到Docker主机。但是,通常会考虑它docker-proxy
是解决这些问题的不雅方法 上面突出显示,当有大量的容器端口时 暴露,它消耗了相当多的记忆。之前的尝试 为了消除docker-proxy
的依赖性,但是这个犯规了 RHEL 6.x和CentOS 6.x中老化内核的局限性, Docker项目认为有责任支持。因此,docker-proxy
仍然是Docker体验的主要组成部分 在所有Docker版本中,直到当前版本1.5。在我写的时候 版本1.6即将发布,并且已经发生了变化 删除docker-proxy
的自动要求,我会这样做 在另一篇文章中介绍。
Docker现在包含disable the userland proxy with --userland-proxy=false
的守护程序运行时选项。这是在v1.7中引入的。
禁用userland代理时,few似乎有bugs边缘情况exist。还有IPV6 issues
有一个开放的GitHub问题,用于禁用userland proxy by default(Docker不再支持RHEL6)。
除了以这种方式实施之外,似乎没有理由。单个进程应该能够处理容器的所有端口映射
proxy implementation和package看起来干净并且在内置的Go功能中使用,所以这可能只是Go的初始垃圾收集限制,允许它增长到~5MB。 < / p>
编辑:内存使用情况为been improved in Docker 1.12。每个端口仍然有一个进程,但每个进程现在只使用~750k的私有内存空间。