Skip to content
60.Docker»30.Cgroups»LV020-Docker中的应用.md

LV020-Docker中的应用

接下来我们看看 docker 是怎么使用 Cgroups 的。

一、测试环境

1. Windows

markdown
版本	       Windows 11 专业版
版本号	      23H2
安装日期	  2024/9/16
操作系统版本  22631.4169
体验	       Windows Feature Experience Pack 1000.22700.1034.0

其中 Windows 通过连接路由器的 WiFi 上网,

2. Ubuntu

Ubuntu 安装在 Windows 中的 VMware 中。

  • VMware
markdown
产品:VMware® Workstation 17 Pro
版本:17.6.0 build-24238078
  • Ubuntu
markdown
# uname -a
Linux sumu-vm 5.15.0-139-generic #149~20.04.1-Ubuntu SMP Wed Apr 16 08:29:56 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux

# lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 20.04.6 LTS
Release:	20.04
Codename:	focal

二、Docker 下的应用

1. docker run 命令

当你使用 docker run 并指定资源限制参数时,Docker 引擎就是在幕后操作 Cgroups 文件系统。

  • --cpus=<value>: 限制容器能使用的 CPU 核心数。例如 --cpus="1.5" 表示最多使用 1.5 个 CPU 核心的计算量。Docker 会自动计算 cpu.cfs_period_uscpu.cfs_quota_us
  • --cpu-quota=<value>: 直接设置 cpu.cfs_quota_us。通常与 --cpu-period (默认 100000) 配合使用。--cpu-quota=30000 效果类似上面手动设置的 30%。
  • -m--memory=<value>: 限制容器能使用的最大内存量,例如 -m 200m。Docker 会设置 memory.limit_in_bytes
  • --memory-swap=<value>: 限制内存+Swap 的总使用量。通常设置为与 -m 相同的值来禁用 Swap,或者设置为 -1 表示不限制 Swap。
  • --blkio-weight=<value>: 设置块 I/O 的相对权重(非绝对限制)。
  • --device-read-bps, --device-write-bps: 限制特定设备的读写速率。

2. Docker 如何使用 Cgroups?

Docker 通过 libcontainer 与内核交互,为每个容器创建独立的控制组:

shell
sumu@sumu-vm:/sys/fs/cgroup$ tree -L 2
.
├── blkio
│   ├── blkio.prio.class
│   ├── #...
│   ├── docker
│   ├── #...
│   ├── tasks
│   └── user.slice
├── #...
├── memory
│   ├── cgroup.clone_children
│   ├── cgroup.event_control
│   ├── cgroup.procs
│   ├── cgroup.sane_behavior
│   ├── docker
│   ├── init.scope
│   ├── #...
│   ├── tasks
│   └── user.slice
#...
53 directories, 177 files

可以看到 /sys/fs/cgroup 的每个目录下其实都有一个 docker 目录,里面也存在一些文件:

image-20251102233902621

Docker 创建容器时,Docker 会根据启动容器的参数,在对应的 cgroups 子系统下创建以容器 ID 为名称的目录, 然后根据容器启动时设置的资源限制参数, 修改对应的 cgroups 子系统资源限制文件, 从而达到资源限制的效果。这个我们后面就会看到了。

三、限制容器内存实例

1. 限制容器内存

我们使用下面的命令创建两个 alpine 容器:

shell
docker run -it -d -m=1g alpine
docker run -it -d -m=100m alpine

2. 查看 Cgroups 内存子系统

然后我们进入 cgroups 内存子系统的 docker 目录,使用 ls 命令查看一下该目录下的内容:

shell
cd /sys/fs/cgroup/memory/docker
ls -a

【例】

image-20251102234638473

会发现这里出现了一个名为 7b6865f89ee875c0d6fc1d1a771f358aec08eb0df614b2afdea29e587e484b14 的目录,刚好和 docker 容器的 container_id 对应,我们看一下这个目录下有哪些文件:

image-20251102234318787

会发现这里也是一堆的文件,我们看一下 memory.limit_in_bytes 文件内容:

image-20251102234825296

计算一下,1073741824 就是 1GB,104857600 就是 100MB。

莫道桑榆晚 为霞尚满天.