AppArmor配置文件中通过deny语句明确禁止访问宿主机敏感路径最有效,如deny /etc/ rwklx, deny /boot/ rwklx, deny /root/ rwklx,确保递归匹配子目录,rwklx覆盖读写链接锁定执行,避免仅写deny /etc导致规则失效。

AppArmor配置文件里怎么写拒绝访问宿主机敏感路径
直接在配置文件中用deny语句明确禁止容器进程访问特定路径,是限制宿主机目录访问最有效的方式。关键不是“允许什么”,而是“禁止什么”——因为默认策略(如docker-default)本身已放行大量基础路径,盲目追加allow反而容易遗漏或冲突。
典型拒绝规则写法如下(以禁止访问/etc、/boot、/root为例):
deny /etc/** rwklx, deny /boot/** rwklx, deny /root/** rwklx, deny /proc/sys/** w, deny /sys/** w,
-
rwklx表示禁止读(r)、写(w)、链接(l)、锁定(k)和执行(x),覆盖绝大多数越权操作场景 - 路径末尾的
**确保递归匹配子目录,避免漏掉/etc/shadow这类深层文件 - 对
/proc/sys和/sys加w限制,可防容器修改内核参数(如net.ipv4.ip_forward) - 不要只写
deny /etc/——不带**时,AppArmor 仅匹配该目录自身,不生效于其下文件
如何让Docker容器加载自定义AppArmor策略
Docker不会自动识别你放在/etc/apparmor.d/下的新策略文件,必须显式加载并绑定到容器启动过程。分两步:先让内核认识这个策略,再让容器运行时引用它。
假设你创建了策略文件/etc/apparmor.d/container-restrict:
使用 Python 脚本下载 Docker 镜像并打包为 tar 文件。用户说“下载镜像”“拉取镜像”“pull xxx”“帮我下载 nginx 镜像”等时触发。支持 SOCKS5 代理直连(推荐)和国内镜像站加速两种模式。
- 用
apparmor_parser -r /etc/apparmor.d/container-restrict加载(-r支持重复加载,无需先删除) - 运行容器时通过
--security-opt apparmor=container-restrict指定策略名(注意:不是文件路径,是profile名,即文件首行profile container-restrict中的名字) - 验证是否生效:
docker exec -it <container> cat /proc/self/attr/current</container>,输出应为container-restrict (enforce) - 若报错
apparmor: profile not found,说明apparmor_parser未成功加载,检查语法(如括号匹配、逗号结尾)和权限(需root)
为什么容器挂载了宿主机目录却仍被AppArmor拦截
常见现象是docker run -v /host/data:/app/data ...后,容器内ls /app/data报Permission denied,但ls /host/data在宿主机上完全可读——这大概率不是挂载权限问题,而是AppArmor策略未覆盖挂载点路径。
- AppArmor按进程视角做路径检查,容器内看到的
/app/data实际映射到宿主机/host/data,但策略中若只写了deny /host/**,而没写deny /app/data/**,则拦截不生效;反之亦然 - 更稳妥的做法是在策略中同时约束两端路径:
deny /host/data/** rwklx,+deny /app/data/** rwklx, - 若使用
:z或:ZSELinux标签,AppArmor不会干涉SELinux上下文,但两者叠加时,任一模块拒绝即失败;此时应优先确认AppArmor日志:dmesg | grep -i apparmor,看具体哪条规则触发了denial - 注意
docker-default策略本身已禁用mount、umount等调用,所以即使挂载成功,容器也无法在运行时重新挂载其他路径——这点常被忽略
生产环境启用AppArmor限制前必须验证的三件事
AppArmor策略一旦进入enforce模式,违规操作会立即被阻断,可能导致服务静默失败。上线前务必实测以下三点:
- 确认容器内应用真实需要的路径——比如Nginx需要读
/etc/nginx/conf.d/、写/var/log/nginx/,这些路径不能被deny误伤;可用strace -e trace=openat,openat2,statx在开发环境抓取实际系统调用路径 - 检查
/proc/self/attr/current输出是否含预期profile名,且状态为(enforce)而非(complain);后者只会记录不拦截,容易误判策略已生效 - 验证日志落盘路径是否在允许范围内——很多应用默认写
/tmp或/var/tmp,而docker-default策略对这些路径是放行的,但你的自定义策略若没显式allow,就会被默认拒绝(AppArmor默认deny)
最易被忽略的是策略加载时机:Docker daemon重启后,之前用apparmor_parser加载的策略仍在内核中,但若系统重启而没配置开机自动加载,策略就丢失了。建议将apparmor_parser -r /etc/apparmor.d/container-restrict加入/etc/rc.local或systemd service。

















