当前位置:首页 > 内存 > 正文

docker容器占用多少内存

  • 内存
  • 2024-07-03 03:44:53
  • 1721

一、Docker容器达到MemoryLimit后的行为

如果某个容器需要的内存多于整个主机上可用的内存,内核可能会终止该容器或Docker守护进程(daemon)以释放内存,这可能会导致所有服务不可用。为了避免这个错误,我们应该为每个容器限制相应的内存。

我们可以在Docker-Compose或DockerStack环境中使用以下配置来限制容器的内存使用:

接下来我们来了解一下上面的配置

容器允许的最大内存使用量,最小值为4MB。

如果容器使用超过限制的内存,就会发生这种情况。什么,触发程序GC还是kill?

不幸的是,官方文档似乎没有详细解释内存限制,但是Google可以提供帮助,你可以在下面的文章中找到一些提示:

实验表明,如果程序使用的内存超过了“”限制(cgroup的resource_management_guide/sec-memory),容器就会被杀死。

简单,你可以使用Redis使用容器:限制内存为10MB,向Redis添加大量数据,然后检查容器的状态。

其实我们并不希望容器需要直接终止,但是如果Redis的Cleanup逻辑触发,服务会在一定时间内不可用(虽然会重启)。

怎么办?

经过多方排查,发现官方提供的其他参数都无法解决这个问题,包括“memory-reservation”、“kernel-memory”和“oom-kill-disable”。

看来这个问题是存在的如果我们只使用了想要触发的程序的GC,那该怎么办?

当一个程序发现内存不够时,一般都会有自己的GC机制,但是正如本文所描述的了解DockerContainerMemoryLimitBehavior的文章提到,在Docker容器中运行的程序的内存限制是不可见的,程序仍然适用大于Docker限制的内存限制。内存最终会导致OOMKill。

为此,我们需要对程序进行额外的配置,例如Redis的Maxmemory配置和Java的JVM配置。不幸的是,并不是所有程序都有自己的内存限制配置,就像本例中MySQL建议降低程序性能并确保为程序保留足够的内存。

如果您的服务器上启用了交换,还可能存在一个问题:当容器到达内存时,会特别慢,达到限制时磁盘IO会很高(峰值)。

这是因为我们也忽略了一个参数:内存交换。如果未设置内存交换,则其值是内存限制的两倍。如果设置了limit-memory=300M且未设置memory-swap,则表示容器可以使用300M内存和300MSwap。container/resource_constraints/#--memory-swap-details

值得一提的是,swap并不是无损的,相反,它非常慢(使用磁盘而不是内存),我们应该禁用它。

但是,遗憾的是,composefilev3不支持设置内存交换限制。

别无选择,只能关闭主机的交换。

总结如下当容器达到内存限制时发送: