Docker的 – 内存开关不能按预期工作

前言

我正在写一个小小的演示文稿,列出使用Docker时的一些“疑难杂症”,而且我已经碰到了自己的一个。

在解释让Docker在没有内存限制的情况下运行的危险时,我发现它并不像我预期的那样运行。

我用一个PHP脚本创build了一个Docker镜像,它将recursion地创build数组来消耗内存,报告当前使用了多less内存。 如果没有内存限制,脚本会以1GB的速度自杀。

你可以在这里获取图像: https : //hub.docker.com/r/gisleburt/my-memory-hog
你可以在这里看到源代码: https : //github.com/Gisleburt/my-memory-hog

我的期望是,以下内容将阻止脚本超出128mb的内存。

docker run -it --memory=128m --memory-swap=0 gisleburt/my-memory-hog 

但是,在OSX(本地和使用虚拟框驱动程序的docker-machine)上,docker实际上在250mb之前的脚本。 在Ubuntu上,脚本达到1GB,并自杀。

Weirder仍然认为,如果我们检查docker的docker stats ,我们可以看到容器实际上并没有超过它的内存限制。 实际上,在Ubuntu上使用--memory=4m运行时, --memory=4m docker stats仍然表示它不会超过4mb,即使脚本以1gb完成。 在Mac上,限制到4mb,杀死剧烈的5-6mb大关。

我假设我错过了分配内存的方式,但是我不知道它是什么。

为什么docker容器中的脚本似乎比docker容器使用更多的内存? 容器内部和外部的内存发生了什么变化?

版本信息

Mac客户端:

 Client: Version: 1.12.3 API version: 1.24 Go version: go1.6.3 Git commit: 6b644ec Built: Thu Oct 27 00:09:21 2016 OS/Arch: darwin/amd64 Experimental: true 

Mac原生:

 Server: Version: 1.12.3 API version: 1.24 Go version: go1.6.3 Git commit: 6b644ec Built: Wed Oct 26 23:26:11 2016 OS/Arch: linux/amd64 

Mac虚拟机箱:

 Server: Version: 1.12.3 API version: 1.24 Go version: go1.6.3 Git commit: 6b644ec Built: Thu Oct 27 00:09:21 2016 OS/Arch: linux/amd64 Experimental: true 

Ubuntu客户端:

 Client: Version: 1.12.3 API version: 1.24 Go version: go1.6.3 Git commit: 6b644ec Built: Wed Oct 26 22:01:48 2016 OS/Arch: linux/amd64 

Ubuntu引擎:

 Server: Version: 1.12.3 API version: 1.24 Go version: go1.6.3 Git commit: 6b644ec Built: Wed Oct 26 22:01:48 2016 OS/Arch: linux/amd64 

在我们技术部门的许多人的帮助下,特别是我们平台运营团队的一个成员的帮助下,我们研究了发生了什么, 参考指南中提到了这一点

--memory-swap总内存限制( 内存+交换 ,格式:<number> [<unit>])。 数字是一个正整数。 单位可以是b,k,m或g中的一个。

说白了,– --memory-swap是可用的内存总量,包括常驻和交换。

为了获得所需的效果,您必须运行:

 docker run -it --memory=128m --memory-swap=128m gisleburt/my-memory-hog 

在这个例子中, memory = 128mbmemory + swap = 128mb因此swap = 0

同样有意义的是,你不能为--memory-swap指定一个大于0,小于--memory

此外,虽然--memory-swap=-1通过交换给你一个“无限”的内存量,但由于某些原因,设置--memory-swap=0似乎使内存和交换的大小相同 ,的内存两次你所期待的。

你也可以使用--memory-swappiness=0closures交换。 虽然交换文件可能会被创build,但不会被写入,因此不会占用比空文件更多的磁盘空间。

TL; DR:

 --memory = RES --memory-swap = VIRT = RES + SWAP