容器镜像层本身只读,真正需防护的是运行时可写层和挂载路径;应通过--read-only、tmpfs挂载、chattr +i、seccomp/apparmor及构建阶段隔离等多层手段,阻止对敏感二进制文件的覆盖或篡改。
容器镜像层本身是只读的,运行中根本无法被修改——这是 docker/oci 的底层设计原则。所谓“逆向修改镜像层”,在技术上不成立。真正需要防范的,是攻击者利用容器可写层(如 overlay2 的 upperdir)或挂载路径(如 volume、bind mount),覆盖、替换或加密原本存于镜像中的敏感二进制文件(例如 license 工具、密钥管理器等)。
因此,“禁止容器运行中逆向修改镜像层”的实质,是切断勒索软件或恶意进程对关键二进制文件的实际写入能力。核心不在“改镜像层”,而在“锁住运行时落地路径”。
让根文件系统彻底只读(ro rootfs)
这是最直接有效的第一道防线。--read-only 会强制整个容器根文件系统(含所有镜像层 + init layer)为只读状态,任何 mv、cp -f、echo > 等覆盖操作都会失败。
- 使用
docker run --read-only启动容器 - 所有需写入路径(如
/tmp、/run、/var/log)必须显式挂载:-
--tmpfs /tmp:rw,size=64m,mode=1777 -
--tmpfs /run:rw,size=32m,mode=0755
-
-
/proc和/sys以只读方式挂载:-v /proc:/proc:ro -v /sys:/sys:ro - 若应用需写配置,应挂载专用 volume 或 tmpfs,并限定属主与权限
✅ 效果:/usr/bin/lictool 这类镜像内置二进制,无法被 mv /tmp/malware /usr/bin/lictool 覆盖;即使下载了恶意 payload,也无法持久落盘。
对宿主机挂载的敏感文件启用不可变属性(chattr +i)
仅适用于通过 -v /host/path:/container/path:ro 方式绑定挂载的外部二进制(如硬件授权工具)。
- 在宿主机执行(需 root):
chattr +i /host/path/lictool.bin
- 验证是否生效:
lsattr /host/path/lictool.bin # 应显示 'i' 标志
- ⚠️ 注意:不可对
/etc/passwd、/etc/shadow等动态文件加+i,否则容器初始化失败;仅限静态、只读用途的二进制。
该机制由 ext4/xfs 文件系统内核级支持,root 也无法绕过,除非先 chattr -i。
用 seccomp 或 AppArmor 拦截危险系统调用
即使文件路径可写,也可从行为层面阻止篡改动作。
- 禁止
openat(..., O_TRUNC)、renameat2(..., RENAME_EXCHANGE)、unlinkat等覆盖/删除类调用 - 示例 seccomp profile 可限制
chmod、chown、mknod、mount等权限提升相关 syscall - Kubernetes 中可通过 PodSecurityPolicy 或 SecurityContext 配置
seccompProfile.type: Localhost
✅ 效果:即便攻击者拿到 shell,执行 cp malware /usr/bin/lictool 也会因 EPERM 被内核拒绝,而非静默成功。
构建阶段隔离敏感二进制,避免运行时存在
最彻底的方案:不让敏感文件出现在容器运行时文件系统中。
- 将 license 校验逻辑封装为独立服务(如 sidecar 或远程 API),主容器只发起 HTTP 请求校验
- 或使用 eBPF 工具(如 libbpf + CO-RE)在内核态完成授权验证,无需部署二进制
- 若必须内置,应在构建末期用
COPY --chown=root:root --chmod=0555显式设为只读可执行,并确保 UID/GID 不具备写权限
这样,即使容器被攻陷,也找不到可篡改的目标文件。
不复杂但容易忽略











