不可不知的七个 Docker 优秀实践
![不可不知的七个Docker优秀实践](https://static001.geekbang.org/infoq/ba/ba49fa2197cedeaf7a5b447f312f1d14.webp)
Docker 是流行的容器化软件,但不是每个人都在高效地使用它。如果您不遵循 Docker 的优秀实践,您的应用程序就很容易受到安全问题或性能问题的影响。
本文介绍了您可以用来高效地使用 Docker 功能的几个最佳实践。这些措施提高了安全性,并确保您创建易于维护的 Docker 文件。
1.使用官方 Docker 镜像
在容器化处理应用程序时,必须使用 Docker 镜像。您可以使用自定义配置构建镜像,也可以使用 Docker 的官方镜像。
构建自己的镜像需要您自行处理所有配置。比如说,若为 Node.js 应用程序构建镜像,您必须下载 Node.js 及其依赖项。这个过程很耗时,可能不会生成所有正确的配置。
Docker 建议您使用官方的 Node.js 镜像,它包含所有正确的依赖项。Docker 镜像有更好的安全措施,具有轻量级的优点,并针对各种环境进行了测试。你可以在 Docker 的官方镜像页面上找到官方镜像。
![](https://static001.geekbang.org/infoq/06/06f1e8f8fcf891fb44d2c859f5880d72.png)
2.使用 Docker 镜像的特定版本
当您拉取官方镜像时,它通常带有最新标签,这代表该镜像的最新更新版本。每当使用该镜像构建容器,它都是上一个容器的不同版本。
使用不同的 Docker 镜像版本进行构建可能导致应用程序出现不可预测的行为。版本可能会与其他依赖项冲突,最终导致应用程序失败。
Docker 建议您使用特定版本的镜像进行拉取和构建。官方镜像也有说明文档,介绍了最常见的用例。
比如说,使用 docker pull alpine:3.18.3,而不是 docker pull alpine。Docker 将提取该特定版本。然后,您可以在后续构建中使用它,从而减少应用程序中的错误。您可以在 Docker 官方镜像页面的 Supported 标签和相应的 Dockerfile 链接下找到镜像的特定版本:
![](https://static001.geekbang.org/infoq/b2/b2a70a2b3552e1685c7b6fcf7932a1f3.png)
3.扫描镜像以查找安全漏洞
如何确定想要构建的镜像没有安全漏洞?扫描就行。可以使用 Docker scan 命令扫描 Docker 镜像。语法如下:
您必须先登录到 Docker 才能扫描镜像。
然后,扫描您想要检查的特定镜像:
![](https://static001.geekbang.org/infoq/a7/a7942aab308d826fcffbb164f3d0f156.png)
一种名为 Synk 的工具可以扫描镜像,根据严重程度列出任何漏洞。您可以看到漏洞的类型和指向相关信息的链接(包括如何修复它)。您可以从扫描结果中判断镜像对您的应用程序而言是否足够安全。
4.使用小型 Docker 镜像
当您拉取 Docker 镜像时,它附带所有系统实用程序。这增加了不需要的工具的镜像大小。
大型 Docker 镜像占用存储空间,并且减慢容器的运行速度。它们存在安全漏洞的可能性也更大。
您可以使用 Alpine 镜像减小 Docker 镜像的大小。Alpine 镜像是轻量级的,只附带必要的工具。它们减少了存储空间,使应用程序运行起来更快速、更高效。
可以在 Docker 上找到大多数官方镜像的 Alpine 版本。下面是 PostgreSQL 的 Alpine 版本的示例:
![](https://static001.geekbang.org/infoq/f6/f665751d3325407d399f708ff00bc2f5.png)
5.优化缓存镜像层
Dockerfile 中的每个命令代表镜像上的一个层。这些层有不同的实用程序,并执行不同的功能。如果您查看 Docker Hub 上的官方镜像,将会看到用于创建它们的说明。
Dockerfile 包含创建镜像所需的全部内容。这就是为什么许多开发人员青睐 Docker 而不是虚拟机的原因之一。
下面是示例 Alpine 镜像的结构:
![](https://static001.geekbang.org/infoq/c5/c5509b71613b96c1f198dd817406d292.png)
当您构建基于镜像的应用程序时,实际上在为镜像添加更多的层。Docker 从上到下在 Dockerfile 上运行指令,如果一个层发生了变化,Docker 必须重建后续的层。
最佳实践是将您的 Dockerfile 按照由更改最少的文件到更改最频繁的文件这个顺序排列。不会改变的指令(比如安装)可以放在文件的顶部。
当您修改一个文件时,Docker 根据修改后的文件进行构建,并在上面缓存未修改的文件。因此,流程运行速度更快。
![](https://static001.geekbang.org/infoq/b8/b8b653536e3953e695d21aca6abf05f5.png)
请看上图所示的例子。如果应用程序文件发生了变化,Docker 将从那里构建,它没必要再次安装 NPM 包。
如果从镜像构建,该过程将比从头重建所有其他层运行得更快。缓存也加快了从 Docker Hub 拉取和推送镜像的速度。
6.使用.dockerignore 文件
在使用 Dockerfile 构建镜像时,您可能希望保留某些信息的私密性。一些文件和文件夹可能是项目的一部分,但您不希望将它们包含在构建过程中。
使用.dockerignore 文件可以大大减小镜像大小。这是由于构建过程只包含必要的文件。它还有助于保持文件的私密性,避免暴露密钥或密码。
.dockerignore 文件是您在与 Dockerfile 相同的文件夹中创建的一个文件。它是一个文本文件,酷似.gitignore 文件,含有您不希望在构建过程中包含的任何文件的名称。
这里有一个例子:
![](https://static001.geekbang.org/infoq/4a/4aa1803e3f7120fd9eb495708b75b3a3.png)
7.使用最小权限用户原则
默认情况下,Docker 使用 root 用户作为管理员以便获得运行命令的权限,但这种做法不好。如果其中一个容器存在漏洞,黑客就可以访问 Docker 主机。
为了避免这种情况,应创建专用的用户和用户组。您可以为用户组设置相应的权限,以保护敏感信息。如果用户受到危及,您可以在不暴露整个项目的情况下删除该用户。
下面这个例子展示了如何创建用户并设置权限:
![](https://static001.geekbang.org/infoq/71/7151b45a4dc9ae562ebafa2cbaaac879.png)
一些基本镜像在其中创建了伪用户。您可以使用已安装的用户,而不是 root 用户权限。
最佳实践是减少漏洞和编写更简洁代码的好方法。您可以将许多最佳实践应用于使用的每项 Docker 特性。
一个组织良好的项目可以更容易与 Kubernetes 等其他编排工具进行同步。您可以从本文中概述的这些方法入手,在学习 Docker 的过程中采用更多的方法。
8.推荐一款开发工具
一款基于 jar · /Docker 部署方式的开发平台。
JNPF 快速开发平台,很多人都用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。原理是将开发过程中某些重复出现的场景、流程,具象化成一个个组件、api、数据库接口,避免了重复造轮子。因而极大的提高了程序员的生产效率。
官网: https://www.jnpfsoft.com?infoq ,如果你有闲暇时间,可以做个知识拓展。
这是一个基于 Java Boot/.Net Core 构建的简单、跨平台快速开发框架。前后端封装了上千个常用类,方便扩展;集成了代码生成器,支持前后端业务代码生成,满足快速开发;框架集成了表单、报表、图表、大屏等各种常用的 Demo 方便直接使用;后端框架支持 Vue2、Vue3;支持本地化部署,也支持 K8S 部署。
为了支撑更高技术要求的应用开发,从数据库建模、Web API 构建到页面设计,与传统软件开发几乎没有差异,只是通过低代码可视化模式,减少了构建“增删改查”功能的重复劳动。
作为开发者,永远是动手>理解,你可以尝试基于 JNPF 自己搭建一个应用。
版权声明: 本文为 InfoQ 作者【树上有只程序猿】的原创文章。
原文链接:【http://xie.infoq.cn/article/0e1239e08b0d5245a580a3915】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论