序言
我正在写一个小演示文稿来列出使用 Docker 时的一些“陷阱”,我也遇到了自己的一个问题。
在解释让 Docker 在没有内存限制的情况下运行的危险时,我发现它的行为不像我预期的那样。
我使用 PHP 脚本创建了一个 docker 镜像,该脚本将递归地创建数组以耗尽内存,报告当前使用了多少内存。如果没有设置内存限制,脚本会在 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 并杀死自己。
更奇怪的是,如果我们检查
docker stats
发生了什么,我们可以看到容器实际上并没有超过它的内存限制。实际上,使用 --memory=4m
运行在 Ubuntu 上,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
最佳答案
在我们技术部门的一些人,特别是我们平台运营团队的一名成员的帮助下,我们弄清楚了发生了什么,并在 reference guide 中有所提及。 .
--memory-swap
Total memory limit (memory + swap, format: <number>[<unit>]). Number is a positive integer. Unit can be one of b, k, m, or g.
说白了,
--memory-swap
是可用的内存总量,包括常驻内存和交换内存。为了获得预期的效果,您必须运行:
docker run -it --memory=128m --memory-swap=128m gisleburt/my-memory-hog
在此示例中
memory = 128mb
, 和 memory + swap = 128mb
因此swap = 0
.不能为
--memory-swap
指定数字也是有道理的。大于 0,但小于 --memory
.此外,虽然
--memory-swap=-1
通过交换为您提供“无限”的内存量,出于某种原因,设置 --memory-swap=0
似乎使内存和交换 同尺寸 ,为您提供两倍于预期的内存总量。您也可以使用
--memory-swappiness=0
关闭交换。 .尽管可能会创建交换文件,但它不会被写入,因此不会占用比空文件更多的磁盘空间。TL;DR:
--memory = RES
--memory-swap = VIRT = RES + SWAP
关于memory - Docker 的 --memory 开关无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40485302/