Docker Compose 本身不支持物理内存锁定,需通过三步间接实现:设置 memory 和 memswap_limit 硬限制禁用 swap、添加 CAP_IPC_LOCK 能力、配置 ulimit -l 提升 RLIMIT_MEMLOCK 上限,再由应用层调用 mlock 等系统调用完成锁定。
直接说重点:Docker Compose 本身不支持物理内存锁定(如 mlock、memlock),它无法让容器进程将内存页长期驻留 RAM、禁止 swap 或绕过内核内存管理。所谓“物理内存锁定”是操作系统级行为,需在容器内由应用主动调用 mlock() 系统调用,且容器必须具备对应权限(CAP_IPC_LOCK)和足够 ulimit -l 限制。
但你可以通过 Compose 间接构建支持内存锁定的运行环境——关键在于三步配合:配置资源硬限 + 授予特权能力 + 设置内存参数防止 swap 干扰。
内存锁定的前提是容器有明确、稳定的物理内存边界。若不限制,内核可能因整体内存压力触发 OOM Killer,直接终止整个容器(而非仅释放部分页),导致锁定失效甚至服务中断。
memory 硬限制,并同步配平 memswap_limit memswap_limit = memory,即禁用 swap 扩容deploy: resources: limits: memory: 1g memswap_limit: 1g # ⚠️ 不是 mem_swap 或 swap,注意字段名
说明:
memswap_limit是 Docker 原生字段(非 Compose 自定义),它控制memory + swap总量。设为与memory相同值,等效于--memory-swap=1g,彻底关闭 swap 使用空间,防止锁定失败后被换出。
Linux 中调用 mlock() / mlockall() 需要 CAP_IPC_LOCK 能力。默认容器无此权限,必须显式添加:
deploy: resources: limits: memory: 1g memswap_limit: 1g privileged: false cap_add: - IPC_LOCK
注意:不要启用
privileged: true—— 权限过大且不必要。cap_add: ["IPC_LOCK"]精准授权即可。同时确认宿主机未全局禁用该能力(检查/proc/sys/kernel/cap_last_cap和security.bpf等限制)。
即使有了 CAP_IPC_LOCK,进程仍受 RLIMIT_MEMLOCK 限制(默认常为 64KB)。若应用需锁定数百 MB 内存,必须提高该 limit:
deploy: resources: limits: memory: 1g memswap_limit: 1g cap_add: - IPC_LOCK ulimits: memlock: soft: 1073741824 # 1GB,单位字节 hard: 1073741824
提示:
soft和hard建议设为相同值,避免运行时因 soft limit 触发ENOMEM;数值需 ≤ 容器memory限制(此处 1g),否则启动会失败。
Compose 只提供环境,锁定动作必须由应用完成。常见方式包括:
-XX:+UseLargePages + -XX:LargePageSizeInBytes=2M(需宿主机配置 hugepages) unix.Mlock() 或使用 runtime.LockOSThread() 配合 mmap(MAP_LOCKED) shared_preload_libraries = 'pg_prewarm' 并启用 huge_pages=on mlock(ptr, len) 或 mlockall(MCL_CURRENT | MCL_FUTURE)
关键提醒:锁定内存不可被 swap,也不参与内核 page reclaim,因此总量不能超过容器
memory限制,否则申请失败或触发 OOM。
容器内验证是否生效,可运行:
cat /proc/self/status | grep ^CapEff # 查看 IPC_LOCK 是否生效 ulimit -l # 检查 memlock 限制 grep -i lock /proc/self/status # 查看 locked memory 字段