1. 前言
Docker是一种开源的应用容器引擎,允许开发人员将应用程序及其依赖打包到一个可移动的镜像中,并在任何Linux设备运行。
然而,随着应用程序和依赖项的增加,Docker镜像的大小可能会迅速增长,这可能会影响到应用的部署速度和运行效率。
因此,了解如何压缩Docker镜像成为了一个重要的技术需求。本文将学习几种可行的Docker镜像压缩技术。
具体包括:
- 多阶段构建(Multi-stage builds)
- 优化Dockerfile
- docker-slim
- squash参数
- docker export/import
参考文档:
2. 镜像压缩技术概述
2.1. 多阶段构建(Multi-stage builds)
在Docker 17.05版本之后,引入了多阶段构建的功能。多阶段构建可以让你在一个Dockerfile中使用多个FROM语句。每个FROM语句可以看作是新的阶段的开始,另一个阶段可以基于前一个阶段,你只需要最终那个小型且包含所有产物的阶段。例如,在构建一个java应用时,我们可能需要maven来构建应用,但最终运行时,我们可能只需要一个JRE环境,这就是多阶段构建能够帮助你优化镜像大小的地方。
2.2. 优化Dockerfile
优化Dockerfile是另一种有效的压缩Docker镜像的策略。像Alpine Linux这样的更小的基础镜像可以显著减小最终镜像的大小。另外,尽量在Dockerfile中合并RUN命令,因为每个RUN命令都会创建一个新的镜像层。在构建过程结束后清理不需要的缓存和文件也是一个好主意。
2.3. squash参数
docker build命令的squash选项可以将所有的docker层合并为一个层,从而创建一个更小的镜像。需要注意的是,这个选项需要Docker daemon开启experimental实验特性才可使用。
2.4. docker-squash工具
docker-squash,docker镜像压缩工具,可以压缩镜像的最后 n 层。
2.5. docker-slim工具
docker-slim,可以帮助我们自动优化和减小Docker镜像。通过分析我们的Docker镜像,它能够自动压缩和优化它们,使它们更小和更安全。
2.6. docker export/import
docker export 和 docker import 是 Docker 提供的两个指令,它们主要被用来备份和恢复一个 Docker 容器。
也可以用来进行镜像压缩,因为导出再导入后,相当于删除掉了镜像中的所有叠加层,只保留最后的效果。
参考文档:
3. docker export/import实践
3.1. Docker Export
docker export
命令用来将一个正在运行的或者停止的容器导出到一个 tar 文件中。其命令语法如下:
1 | docker export CONTAINER > somefile.tar |
这里 CONTAINER
是需要导出的容器的 ID。export 命令会将容器的文件系统导出成 tar 文件,但需要注意的是,导出操作不会包含容器所使用的历史命令和元数据。也就是说,导出后的容器并不能完全反映原来的容器状态。
3.2. Docker Import
docker import
命令用来从一个 tar 文件或者一个 URL 中创建一个新的文件系统镜像。其命令语法如下:
1 | docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]] |
这里 file 或 URL 是需要导入的文件,REPOSITORY[:TAG]
是可选的镜像仓库和标签。
比如,我们可以将上面导出的 tar 文件导入成一个新的 Docker 镜像:
1 | docker import somefile.tar newimagename:tagname |
这样我们就从 tar 文件中创建了一个新的 Docker 镜像。注意,docker import 操作是创建镜像,而不是创建容器。这个镜像同样也没有原来容器的运行历史和元数据信息。
3.3. 镜像压缩实践
1 | docker create --name test harbor.voidking.com/xxx/yyy:v0.1 tail -f /dev/null |
或者:
1 | docker export $(docker create harbor.voidking.com/xxx/yyy:v0.1) | docker import - harbor.voidking.com/xxx/yyy:v0.1-squashed |
具体能压缩多少,取决于镜像层中误增加和反复修改的内容量。
4. 后记
Docker镜像压缩是一种重要的技术,它可以提高应用的部署速度和运行效率。然而,我们在压缩Docker镜像时,也需要考虑到镜像的可移植性和可维护性。过度的压缩可能会引入复杂性,影响镜像的可读性和可维护性。在实际应用中,我们需要根据具体的需求和条件,选择最合适的压缩策略。