在构建、共享和运行应用程序以及Docker容器安全性时,您需要考虑一些Docker 安全最佳实践。Docker 是一个开源平台,用于构建、共享和运行容器化应用程序。您可以轻松地构建包含您的应用程序的 Docker 映像,在您的团队内或团队外共享它们,并且只需一个命令即可运行您的应用程序。看起来很容易,对吧?然而,它是。
您可能已经知道 Docker 是什么以及它是如何工作的。因此,我们不会详细介绍它。本博客将介绍使用 Docker 平台时需要考虑的12 大 Docker 安全最佳实践。
为什么你需要保护你的 Dockerfile 和容器?
容器化因其在任何地方部署应用程序的灵活性而风靡全球。但是,这也引入了一些安全漏洞。Docker 和 Docker 容器使构建、共享和部署应用程序变得非常容易,这使得在部署后查找、检测、报告和修复安全问题变得非常困难。通过将安全性左移,可以防止和最小化大部分开销。因此,保护从 Dockerfile 到 Docker 容器的所有内容对于确保 Docker 容器安全性至关重要 。
12 大 Docker 安全最佳实践
有许多专业可以从一开始就提高Docker 容器的安全性,即从编写 Dockerfile 到运行 Docker 容器。让我们继续看看可以使 Docker 容器安全到位的 12 大 Docker 安全最佳实践。
1. 保持 Docker 主机和 Docker 引擎与您的 Docker 镜像保持同步
Docker 容器在主机上可用的 Docker 引擎上运行。这些主机可以是 Linux/Mac 或 Windows。Docker 引擎可以是可用版本之一。 使用最新的稳定版本至关重要,它更新了以前版本中的已知问题。这同样适用于主机操作系统。
例如,自 2021 年 12 月 27 日起,如果您使用 Ubuntu 作为主机操作系统,则可以使用 Ubuntu 20.04 LTS 而不是 Ubuntu 16.04 LTS,对于 Docker Engine,您可以使用 20.10.11。查找Docker 发行说明以获取更多信息并检查 Docker 支持的操作系统平台。
重要的是要有更新或补丁,因为每个补丁都会解决CVE-2021-41092等漏洞。这个特定的补丁修复了用于从 CLI 登录 docker registry 的凭据被发送到 registry-1.docker.io 而不是预期的私有 registry 的错误;这曾经是由于错误配置的配置文件(通常是 ~/.docker/config.json )列出了 credsStore 或 credHelpers 而发生的。
参考以下截图了解 Ubuntu OS 的发布周期。
Ubuntu 操作系统的发布周期。
2. 避免在 Dockerfile 指令中存储机密数据
Dockerfile 包含用于创建 Docker 镜像的指令。COPY、RUN、ADD、CMD、ENTRYPOINT 等。这些是一些可能是 Dockerfile 一部分的命令指令。我们还可以根据需要使用 ENV 和 ARGS 在运行时或构建时设置变量。您可以使用 ENV 或 ARGS 指令在 Docker 容器内使用环境变量。在设置环境变量时,您应该注意不要将机密、凭据、密码等分配给 Dockerfile 中的变量,也不应该在任何命令中进行硬编码。将此视为 Dockerfile 安全最佳实践之一,因为忽略它可能会导致潜在的安全威胁,并可能让您付出很多代价。
例如,如果您在 Dockerfile 中对数据库的密码或连接详细信息进行硬编码,将它们分配给环境变量,并将 Dockerfile 上传到公共存储库,那么任何有权访问该存储库的人都可以获得这些凭据并可以访问详细信息或连接到数据库。
FROM mysql:5.7 ENV DATABASE_USERNAME=admin # < - Setting username is acceptable ENV DATABASE_PASSWORD=mypassword@!@#$ # < - Avoid setting password at any cost
3.避免使用不受信任的图像注册表
镜像注册表是存储 Docker 镜像的地方。它可以是私人的或公共的。Docker Hub 是 Docker 官方基于云的 Docker 镜像注册中心,它是您安装时的默认注册中心。如果您不配置任何注册表,则图像将从该公共存储库中提取。
当您从任何公共注册表中提取 Docker 镜像时,请注意来源,因为您可能不知道它们是谁构建的、它们是如何构建的,或者它们是否值得信赖。每当您从不受信任的发布者处提取图像时,请不要忘记验证源注册表和用于构建图像的 Dockerfile。此外,您的 Dockerfile 的基础映像,即 FROM 指令。
FROM
4. 谨防递归复制
在为需要将文件从本地计算机复制到 Docker Image 的应用程序编写 Dockerfile 时,您应该知道使用 COPY 指令复制的内容。您的本地计算机上可能有包含机密数据或秘密的文件。因此,如果这些文件被复制到 Docker 镜像中,任何有权访问容器的人都可以从容器中获取这些文件。因此,仅复制容器中需要的文件而不是复制所有内容非常重要,如以下说明所示,以提高 Docker 容器安全性。
你可以试一试。dockerignor.It可以帮助排除匹配模式的文件和目录,并避免使用 ADD 或 COPY 将不必要的大文件或敏感文件发送到图像。
例如,在下面的 COPY 指令中,当前位置的所有文件都将被复制到 Docker Image 中。所以,你应该始终避免“复制”。./ ”并且应该在 COPY 指令中明确指定文件名为“ COPY package.json ./ ”
5. 在开发过程中扫描图像
Docker 镜像 是从 Dockerfiles 构建的,Dockerfiles 包含使用基础镜像、安装包、启动应用程序等的说明。Dockerfile 还可能包含错误地硬编码在其中的凭据。那么,如果您使用的基础镜像存在一些漏洞,并且 Dockerfile 中硬编码的凭据从使用该 Dockerfile 构建的镜像创建的容器中泄露了怎么办?
扫描图像是识别 Docker 图像中已知安全漏洞的过程,以便您可以在将它们推送到 Docker Hub 或任何其他注册表之前修复它们。
由于 Snyk 和 Docker 合作, 您现在可以直接从 Docker Desktop CLI 运行 Snyk 漏洞扫描。
例如
,您可以通过提供用于创建图像的 Dockerfile 来获得有关 Docker 图像的详细报告。
docker scan --file PATH_TO_DOCKERFILE DOCKER_IMAGE
6. 使用固定标签实现不变性
在 Docker 中,图像上有标签。Docker 镜像最常见和默认的标签是“最新”。因此,如果您没有为图像分配标签,默认情况下它将具有“最新”标签。可以使用相同的标签发布多个镜像,即 Docker 镜像标签不是不可变的。因此,非常重要的是——
为您的图像选择更具体的标签,以便您每次都能获得相同的图像。
更喜欢在您的私人存储库中保留图像的副本。
使用 Docker Content Trust (DCT) 将数字签名用于客户端或运行时验证特定图像标签的完整性和发布者。访问官方文档以了解更多信息。
Dev1拉取myimage:latest imag,在自己的电脑上运行1.1版本的应用,发现应用运行流畅。
稍后,Dev2 拉取相同的图像myimage:latest并在他们的计算机上运行该应用程序,并发现该应用程序出了点问题。
在这里,您确定他们都在运行相同版本的应用程序吗?
答案是否定的,因为在 Dev2 拉取镜像myimage:latest 之前, Dev3 进行了更改并推送了同名myimage:latest 应用程序的不稳定版本 1.2。
现在,当他们部署镜像myimage:latest 时, 它将指向应用程序的不稳定版本 1.2,然后这会破坏生产环境。
7. 皮棉Dockerfile
市场上有各种 Dockerfile linter,用于确保 Dockerfile 遵循Dockerfile 安全最佳实践。Linters 可以帮助您停止构建过程,以防它生成警告;它们遍历您的 Dockerfile 并在 Dockerfile 不遵循最佳实践的情况下发出警告。您可以利用Hadolint,这是一个用于验证内联 bash 和 linting Dockerfile 的开源项目。
8.限制容器资源
默认情况下,在主机上运行的 Docker 容器可以利用所有 RAM 和 CPU。在 Docker 容器遭到破坏的情况下,攻击者可能会尝试使用主机资源来执行恶意活动。此外,如果特定容器开始使用主机的所有资源,则驻留在同一位置的其他容器可能会因资源不可用而受到影响。为避免这种情况,建议在 Docker 容器上设置资源限制,以便它们不会使用超过分配给它们的资源,并有助于提供 Docker 容器安全性。
例如, 如果主机有 1 个 CPU,下面的第一个命令可以保证容器每秒最多使用 50% 的 CPU,第二个命令可以将容器的内存使用限制为 1 GB。
CPU 限制
docker run -it --cpus=".5" ubuntu /bin/bash
内存限制
docker run -it --memory="1g" ubuntu /bin/bash
9. 不要暴露 Docker 守护程序套接字
Docker 与名为 /var/run/docker.sock 的 UNIX 域套接字通信,这是Docker API的主要入口点。如果任何人都有权访问 Docker 守护程序套接字,则也可以获得 root 访问权限。因此,允许任何用户写入 /var/run/docker.sock 或将套接字暴露给容器对系统的其余部分来说是一个很大的 Docker 容器安全风险,因为这会赋予它 root 权限。因此,切勿在 Docker 容器内挂载 /var/run/docker.sock。
例如,切勿使用诸如“-v /var/run/docker.sock:/var/run/docker.sock”之类的选项运行 docker run 命令,并将此视为 Docker 安全最佳实践之一,可以帮助您保持安全系统保护。
10. 以非根用户身份运行容器
根据 sysdig.com 的“ 2021 年容器安全和使用报告”,大多数镜像都过于宽松,58% 的容器以 root 身份运行。这不被认为是 Dockerfile 最佳实践;人们应该避免这样做,因为在极少数情况下,您确实需要使用 root 用户在容器中运行您的进程。为确保您不使用根用户,请始终使用用户名指定“USER”指令。
在 Docker 容器中使用非 root 用户可确保减轻容器运行时中的潜在漏洞并实现 Docker 容器安全。
例如
,始终尝试创建和使用非根用户在容器中运行您的应用程序进程。您需要的非 root 用户可能不存在;因此,您首先必须在使用它之前创建一个。
FROM alpine:3.12 RUN adduser -D non-root-user && chown -R non-root-user /myapp-data # < - Create a user USER non-root-user # < - use a non-root user
11. 使 Docker 镜像尽可能小
许多工件是在整个 Dockerfile 构建过程中创建的,只有在构建时才需要。这些包是运行单元测试、临时文件、机密等的编译或依赖项所必需的。将这些工件保留在基础映像中会增加 Docker 映像的大小,这可能会减慢下载时间并扩大攻击面,因为更多的包是因此,loaded 是 Docker 支持多阶段构建的原因之一。此功能允许您在构建过程中使用大量临时图像,同时只保留最新的图像和您复制到其中的数据。
结果,您有两个图像:
图 1:第一个图像是一个大图像,其中包含许多创建应用程序和运行测试所需的依赖项。
图 2:就大小和库数量而言,这是一个非常小且轻的图像,只有一份在生产环境中运行该程序所需的工件副本。
通过这种方式,您可以采用多阶段构建来构建您的 Docker 镜像,这样可以减小镜像的大小并避免安装不需要的库,这些库会增加潜在安全风险的可能性。
12. 使用最新的 Docker 镜像
由于定期发现新的安全漏洞,保持最新的安全补丁是 Docker 安全的一般最佳实践。因此,使用经常更新的基础镜像并在其之上构建您自己的基础镜像非常重要。没有必要总是去最新的版本,它可能包含重大更改,但您应该有一个版本控制策略。以下是您的基本图像需要考虑的几个要点。
坚持使用稳定或长期支持版本,这些版本更有可能获得安全更新。
在您的基础映像版本到达其生命周期结束并且不再接收更新之前,请准备好删除旧版本并进行迁移。
定期重建您的图像并使用类似的技术从基本发行版中获取最新的软件包