博客

加固 Docker 容器以实现多租户托管:分步隔离指南

了解如何通过实际的安全措施(如非root用户、删除不必要的功能、只读文件系统和网络隔离)来锁定 Docker 容器以适应多租户环境。

摘要

运行多租户 Docker 托管平台需要严密的容器隔离,以防止租户相互干扰或逃逸到宿主机。本指南提供了可立即应用的具体、分步加固流程。您将学习如何配置非root用户、删除不必要的 Linux 功能、将文件系统挂载为只读、通过 cgroups 强制资源限制、隔离网络以及应用 seccomp 或 AppArmor 配置文件。我们还将讨论何时使用虚拟机增强容器以实现最高安全性。最后,您将获得一个清单,系统性地消除常见的容器逃逸向量,确保您的多租户基础设施真正隔离。

多租户容器的实际问题

Docker 容器共享宿主内核,如果隔离配置不当,一个租户理论上可以访问另一个租户的数据、耗尽所有 CPU 甚至逃逸到宿主机。作为托管提供商,您需要在不牺牲容器性能优势的情况下实现严密的边界。许多团队从默认的 Docker 设置开始,这些设置是为开发环境而非生产多租户设计的。好消息是:通过系统化的加固清单,您可以将每个容器锁定到接近虚拟机的隔离水平,同时保留 Docker 的速度。

本文通过实际示例和注意事项逐步讲解每个加固步骤。最后,您将获得可重复的流程来部署安全的多租户容器。

第1步:以非root用户运行容器

默认情况下,Docker 容器以 root 身份运行。如果容器被攻破,攻击者将获得容器内的 root 权限,并可能尝试容器逃逸。首先,在 Dockerfile 中创建一个专用用户并切换到该用户:

FROM ubuntu:22.04
RUN useradd -m appuser
USER appuser

注意事项:某些进程(例如绑定到小于1024的端口)需要 root 权限。在这种情况下,使用 --cap-add 标志仅授予所需的功能,例如 --cap-add=NET_BIND_SERVICE,并且仍然在非root用户下运行该进程。

有关基础隔离的更多信息,请参阅我们的指南:在 Docker 中实现真正的多租户隔离

第2步:删除所有 Linux 功能,仅添加所需的功能

Linux 功能将 root 权限分解为小单元。Docker 容器附带一组默认功能,对于多租户托管来说过于宽松。删除所有功能,仅添加应用程序所需的功能:

docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE my-app

应避免的常见功能:SYS_ADMIN(容器逃逸)、NET_RAW(数据包嗅探)、SYS_PTRACE(进程调试)。使用 docker run 配合 --security-opt no-new-privileges 以防止通过 setuid 二进制文件提升权限。

第3步:将根文件系统挂载为只读

攻击者通常会将恶意脚本写入容器文件系统。通过将根文件系统设置为只读,您可以阻止这种行为:

docker run --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m my-app

--tmpfs/tmp/var/run 等目录创建临时可写挂载。noexec 标志阻止从该挂载执行。这种方法迫使攻击者通过可写目录进行迂回攻击,您可以进行监控。

第4步:使用 cgroups 强制资源限制

不受限制的容器可能通过耗尽宿主内存或 CPU 来执行拒绝服务攻击。使用 Docker 的运行时约束:

docker run --memory=512m --memory-swap=512m --cpus=0.5 --pids-limit=100 my-app
  • --memory--memory-swap 设置硬限制(无交换)。
  • --cpus 限制 CPU。
  • --pids-limit 通过限制进程数量防止 fork 炸弹。

注意事项:资源限制由 cgroups 强制,但无法防止通过网络的数据泄露。请结合网络隔离(下一步)。

第5步:使用 Docker 自定义网络隔离网络

默认情况下,Docker 容器共享一个桥接网络。在多租户设置中,您必须隔离每个租户的网络栈。为每个租户创建一个专用网络:

docker network create tenant-alpha --internal
docker run --network tenant-alpha my-app

使用 --internal 标志阻止出站互联网访问,然后通过 -p 仅暴露必要的端口。有关更高级的网络隔离,请参阅 使用 Docker 隔离保护 Web 应用程序

注意事项:内部网络阻止了跨租户的直接容器间通信,但如果使用宿主网络,DNS 泄漏仍可能发生。坚持使用桥接或覆盖网络。

第6步:应用 Seccomp 和 AppArmor 配置文件

Seccomp 过滤系统调用,而 AppArmor(或 SELinux)强制实施强制访问控制。Docker 提供了一个默认的 seccomp 配置文件,阻止危险的系统调用,如带特定标志的 clone。为了更严格的隔离,创建一个自定义配置文件:

docker run --security-opt seccomp=./custom.json --security-opt apparmor=docker-default my-app

您可以使用 docker run --rm -it --security-opt seccomp=unconfined my-app strace -c -S time 生成基础配置文件,然后进行精简。注意事项:过于严格的配置文件可能会破坏合法功能。在测试环境中彻底测试。

第7步:考虑使用虚拟机的混合隔离

如果您的租户需要绝对隔离(例如受监管行业),请在轻量级虚拟机内运行容器。Sysbox 或 Kata Containers 等工具提供硬件级隔离,同时不牺牲容器速度。这是 Docker 增强型容器隔离(ECI)使用的方法。虽然开销高于裸容器,但每个工作负载的开销远低于完整虚拟机。

有关选择正确隔离级别的更多信息,请阅读 设计多租户 Docker 架构

综合运用:加固清单

  1. 使用非root用户构建容器。
  2. 删除所有功能,仅添加所需功能。
  3. 将文件系统挂载为只读,并使用临时可写挂载。
  4. 设置内存、CPU 和 PID 限制。
  5. 为每个租户创建隔离的 Docker 网络。
  6. 应用自定义 seccomp 和 AppArmor 配置文件。
  7. 评估混合虚拟机容器以满足高安全需求。

结论

容器加固不是一次性任务——它是持续性的纪律。上述步骤构成了多租户托管的安全基线。请记住,没有任何单一措施能保证安全;纵深防御是关键。从基础开始:非root用户和删除功能。然后添加资源限制和网络隔离。对于最敏感的工作负载,将容器与虚拟机结合。通过本指南,您可以自信地部署既高效又安全的多租户 Docker 环境。

Sources (5)