Dockerfile 安全最佳实践

文章首发于个人公众号:「阿拉平平」

这篇文章 [1] 来自于 Cloudberry Engineering,作者总结了在编写 Dockerfile 时有哪些安全的注意点,并开源了一个清单 [2] 用来检测 Dockerfile 是否符合规则。我整理了原文,并对部分内容做了精简。由于自己水平有限,文中难免有疏漏错误之处,欢迎大家在留言区指正,以下是正文。

※※※

容器安全虽然是一个很宽泛的问题,但其实有很多小技巧可以帮助我们降低使用的风险。编写 Dockerfile 时遵循一些规则就是一个很好的出发点。

不要在环境变量中存储保密字典

保密字典(secrets)的发布是一个棘手的问题,很容易出错。对于容器化的应用,可以通过挂载卷或者环境变量的方式显示它们。

使用 ENV 存储 secrets 则是一种糟糕的做法,因为 Dockerfile 通常会和应用一起发布,所以这样就和把 secrets 硬编码到代码里没区别了。

仅使用受信任的基础镜像

容器化应用的供应链攻击来自于构建容器本身的分层结构。

很明显,罪魁祸首就是所用的基础镜像。使用不可信的基础镜像会带来很高的风险,应尽量避免。

Docker 为大多数操作系统和应用提供了官方的基础镜像。使用它们,可以最大程度地降低被破坏的风险。

不要使用 latest 作为基础镜像的标签

使用固定的版本作为基础镜像的标签,可以保证正在构建的容器的预期性。

使用 latest 作为标签会隐性地继承升级包,这种情况轻则可能会影响应用的可靠性,重则可能引入漏洞。

避免执行 curl

从网上拉取东西再在 shell 中运行是一种很糟糕的做法。不幸的是,它是一个简化软件安装的普遍解决方案。

wget https://cloudberry.engineering/absolutely-trustworthy.sh | sh

供应链攻击的风险与此相同,归根结底是信任问题。如果你真的需要在 bash 中执行 curl,请正确执行以下操作:

  • 使用受信任的源
  • 使用一个安全链接
  • 验证下载内容的真实性和完整性

不要升级你的系统

这点可能有些夸张,但原因如下:你想固定软件依赖包的版本,但在执行 apt-get upgrade 后,这些依赖包会升级到最新版本。

进行升级并使用 latest 作为基础镜像的标签,会增加依赖树的不可预测性。

你要做的就是固定基础镜像的版本,仅执行 apt/apk update

尽量不要使用 ADD 指令

ADD 指令的一个功能是构建时获取远程 URL 的内容。

ADD https://cloudberry.engineering/absolutely-trust-me.tar.gz

讽刺的是,官方文档建议使用 curl 作为替代方案。

从安全的角度来看,我给出同样的建议:不要用 ADD。先获取所需的内容,验证好再使用 COPY 指令。如果非用不可,请使用安全链接访问受信任的源。

不要使用 root 用户运行

容器里的 root 用户与宿主机相同,但受 Docker 守护进程配置的限制。无论有什么限制,如果用户突破了容器, 他就有办法获取到对宿主机的完全控制权。

所以不要忽略以 root 用户身份运行所带来的风险。

因此,最好始终指定一个普通用户:

USER hopefullynotroot

请注意,在 Dockerfile 显示设置用户只是一层防护,并不能解决整个运行问题。

相反,我们可以也应该采用深度防御的方案,并在整个堆栈中进一步降低风险:严格配置 Docker 的守护进程或者使用无 root 用户的容器,限制运行时的配置(可以的话,设置 --privileged 参数)等。

不要使用 sudo 命令

既然不使用 root 用户,那么也不应该使用 sudo 命令。

即使你使用的是普通用户,也请检查下 sudoers 文件,确保该用户没有特权。

References

[1] 文章: https://cloudberry.engineering/article/dockerfile-security-best-practices/
[2] 清单:https://github.com/gbrindisi/dockerfile-security

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dockerfile是用于构建Docker镜像的文本文件,其中包含了一系列的指令和配置。以下是一些Dockerfile最佳实践: 1. 使用官方基础镜像:选择一个合适的官方基础镜像作为起点,例如`ubuntu`、`alpine`等。官方镜像通常经过优化和安全性验证。 2. 合理使用镜像层缓存:Docker构建镜像时,每个指令都会创建一个新的镜像层。为了提高构建速度,可以将频繁变动的指令放在后面,将不变的指令放在前面,以充分利用镜像层缓存。 3. 最小化镜像大小:避免在镜像中包含不必要的文件和依赖项。可以使用多阶段构建,将编译环境和运行环境分离,只将必要的文件复制到最终的镜像中。 4. 使用COPY而不是ADD:在复制文件到镜像时,优先使用COPY指令而不是ADD指令。COPY只复制本地文件到镜像中,而ADD还支持URL和解压缩功能,容易引入不必要的复杂性。 5. 指定工作目录:通过WORKDIR指令设置工作目录,使得后续指令的执行路径更加清晰和可预测。 6. 使用健康检查:通过HEALTHCHECK指令添加容器的健康检查机制,以确保容器的正常运行。可以使用CMD或ENTRYPOINT指令来运行健康检查脚本。 7. 清理不必要的文件和依赖项:在构建镜像时,确保删除不再需要的临时文件、缓存和安装包,以减小镜像的大小。 8. 使用环境变量:通过ENV指令设置环境变量,使得容器的配置更加灵活和可配置化。 9. 使用标签管理镜像版本:为镜像添加标签,方便管理和追踪不同版本的镜像。 10. 安全性注意事项:避免在镜像中运行特权进程,确保镜像中的软件包和依赖项是最新的,定期更新基础镜像和应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值