Dockerfile 最佳实践:打造高效且安全的镜像构建
在Docker的世界中,编写生产级的Dockerfiles并非易事。这个开源项目为你提供了一套关于Dockerfile的最佳实践,由经验丰富的开发者Damian Naprawa根据实际工作中的Docker和Kubernetes操作提炼而成。这是一份指导,而非强制规则,但在你不确定如何做时,这里的建议通常是个不错的选择。
Dockerfile最佳实践概览
本项目包含以下一系列实用技巧:
- 尽可能使用官方Docker镜像
- Alpine并不总是最佳选择
- 限制镜像层的数量
- 以非root用户身份运行
- 避免使用低于10000的UID
- 使用静态的UID和GID
- 慎用“latest”标签,选择特定版本的镜像
- 只在CMD中存储参数
- 始终使用COPY而非ADD(仅有一个例外)
- 将
apt-get update
与apt-get install
合并到同一RUN指令中
官方Docker镜像:你的首选基础
官方Docker镜像是经过优化和广泛测试的,能为你的技术提供最可靠的起始点。如果你的技术有官方基础镜像,那么应优先考虑使用。这样可以避免自定义镜像可能带来的安全漏洞或不兼容性问题。
例如,使用官方的.NET SDK镜像比手动安装SDK更简洁有效:
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster
避免过度依赖Alpine
尽管Alpine因其轻量级特性受到青睐,但其性能对于某些技术可能会有影响,并且在安全性方面也有一些争议。在决定是否使用Alpine之前,请权衡其利弊。
简化镜像层数以保持轻量化
每一个RUN
指令都会增加一层镜像,过多的层级会使镜像变得庞大。通过组合命令,你可以有效地减少镜像的层次,保持镜像轻巧。
运行于非root用户下
以非root用户运行容器可以显著降低容器内进程对宿主机潜在的安全威胁。虽然会增加一些权限配置的工作,但这是提升容器安全性的关键步骤。
使用高于10000的UID
使用大于10000的UID可降低与系统特权用户的权限冲突风险,从而提高安全性。
固定的UID和GID
为了方便文件权限管理,建议所有容器使用相同的固定UID和GID。例如,建议使用10000:10001
。
避免滥用"latest"标签
使用具体的major.minor
版本标签,既可以保证构建稳定性,也能及时获取安全更新。同时,使用工具如docker-lock,可以在享受稳定性和安全性的同时,保持构建的可重复性。
只在CMD中设置参数
将命令名保留在ENTRYPOINT
,将参数保存在CMD
,使用户能够直观地传递参数给二进制文件,无需知道具体的命令名。
尽量使用COPY而非ADD
ADD
可能导致MITM攻击、恶意数据源以及路径遍历和Zip Slip漏洞。除非确实需要自动解压tar文件,否则应优先选择COPY
。
合并apt-get update
与apt-get install
避免单独使用apt-get update
,以防因缓存导致的问题,确保每次安装都基于最新的包列表。
这些最佳实践旨在帮助你创建更健壮、更安全的Docker镜像,让你的开发和部署流程更加顺畅。采用这些策略,不仅提升了效率,还能为你的应用程序提供更强的保护。开始使用这份指南,让你的Dockerfile达到新的水平吧!