Docker 和 Podman 中的 Linux Capabilities
在运行 Docker (或 Podman) 容器时,有时即使使用 root
用户或者使用了 sudo
,也会出现 Operation not permitted
的错误信息。这是因为容器中的 root
并不具有完整的 root
权限。这种权限的控制是通过 Linux capabilities 实现的。本文将首先介绍 Linux capabilities 的概念,然后以 Docker 为例介绍如何调整容器的 capabilities,最后介绍 Docker 和 Podman 在默认 capabilities 上的差异,以为容器的开发者和用户提供参考。
Linux Capabilities
经典的 Linux 权限控制模型将用户分为普通用户和特权用户 (例如 root
用户和具有 sudo
权限的用户)。特权用户拥有系统上的所有权限,容易导致安全问题。例如,一个 Web 服务器需要特权以监听 443 或 80 端口,但不应当访问其他用户的文件或修改系统内核;而如果 Web 服务器被攻破,攻击者将获得系统上的所有权限。
Linux capabilities 将系统中的特权分为多个不同的 capabilities,可以通过赋予进程部分特权而不是完整的 root
权限来降低系统的风险。例如,CAP_NET_BIND_SERVICE
允许进程绑定小于 1024 的端口,而不需要完整的 root
权限。Linux capabilities 的列表可以通过 man 7 capabilities
查看。
Docker 中的 Linux Capabilities
与服务器不同,容器不需要完整的 root
权限,因为容器的目的是运行一个或一些特定的应用程序,而不是整个系统。例如:
- 容器通常不需要管理网络和日志,因为容器的网络和日志是由 Docker Engine 管理的。
- 容器通常不需要设置时间,因为它的时间由宿主机提供
- 容器通常不需要运行
reboot
命令,因为容器的生命周期由 Docker Engine 管理
因此,Docker 通过白名单的方式限制了容器的 capabilities,即容器默认仅具有特定的 capabilities。Docker 所使用的 capabilities 可以在这里查看。
如果你希望进一步限制容器的 capabilities 以增加安全性,可以通过 --cap-drop
选项来删除 capabilities。如果容器中的程序确实需要某些 Capabilities,可以通过 --cap-add
选项添加这些 capabilities。对于容器的开发者,在需要额外的 capabilities 时,建议在 README 中明确说明。
Podman 与 Docker 的 Capabilities 差异
Podman 通过进一步限制容器的 capabilities 来获得比 Docker 更高的安全性。Podman 的 capabilities 默认值可以在这里查看。
Podman 的默认 capabilities 比 Docker 更加严格,因此在 Podman 中运行的容器可能会出现更多的 Operation not permitted
错误,例如 sudo
将无法使用 CAP_AUDIT_WRITE
Capability。Podman 用户在运行容器时如果遇到 Operation not permitted
错误而其他人却无法复现,很有可能就是 Podman 的 capabilities 额外限制导致的。
参考资料
Docker 和 Podman 中的 Linux Capabilities
https://blog.caomingjun.com/linux-capabilities-in-docker-and-podman/