两个奇技淫巧,将 Docker 镜像体积减小 99%
对于刚接触容器的人来说,他们很容易被自己构建的 Docker 镜像体积吓到,我只需要一个几 MB 的可执行文件而已,为何镜像的体积会达到 1 GB
以上?本文将会介绍几个奇技淫巧来帮助你精简镜像,同时又不牺牲开发人员和运维人员的操作便利性。本系列文章将分为三个部分:
第一部分着重介绍多阶段构建(multi-stage builds),因为这是镜像精简之路至关重要的一环。在这部分内容中,我会解释静态链接和动态链接的区别,它们对镜像带来的影响,以及如何避免那些不好的影响。中间会穿插一部分对 Alpine
镜像的介绍。
第二部分将会针对不同的语言来选择适当的精简策略,其中主要讨论 Go
,同时也涉及到了 Java
,Node
,Python
,Ruby
和 Rust
。这一部分也会详细介绍 Alpine 镜像的避坑指南。什么?你不知道 Alpine
镜像有哪些坑?我来告诉你。
第三部分将会探讨适用于大多数语言和框架的通用精简策略,例如使用常见的基础镜像、提取可执行文件和减小每一层的体积。同时还会介绍一些更加奇特或激进的工具,例如 Bazel
,Distroless
,DockerSlim
和 UPX
,虽然这些工具在某些特定场景下能带来奇效,但大多情况下会起到反作用。
本文介绍第一部分。
1. 万恶之源
我敢打赌,每一个初次使用自己写好的代码构建 Docker 镜像的人都会被镜像的体积吓到,来看一个例子。
让我们搬出那个屡试不爽的 hello world
C 程序:
/* hello.c */
int main () {
puts("Hello, world!");
return 0;
}
并通过下面的 Dockerfile 构建镜像:
FROM gcc
COPY hello.c .
RUN gcc -o hello hello.c
CMD ["./hello"]
然后你会发现构建成功的镜像体积远远超过了 1 GB
。。。因为该镜像包含了整个 gcc
镜像的内容。
如果使用 Ubuntu
镜像,安装 C 编译器,最后编译程序,你会得到一个大概 300 MB
大小的镜像,比上面的镜像小多了。但还是不够小,因为编译好的可执行文件还不到 20 KB
:
$ ls -l hello
-rwxr-xr-x 1 root root 16384 Nov 18 14:36 hello
类似地,Go 语言版本的 hello world
会得到相同的结果:
package main
import "fmt"
func main () {
fmt.Println("Hello, world!")
}
使用基础镜像 golang
构建的镜像大小是 800 MB
,而编译后的可执行文件只有 2 MB
大小:
$ ls -l hello
-rwxr-xr-x 1 root root 2008801 Jan 15 16:41 hello
还是不太理想,有没有办法大幅度减少镜像的体积呢?往下看。
为了更直观地对比不同镜像的大小,所有镜像都使用相同的镜像名,不同的标签。例如:hello:gcc
,hello:ubuntu
,hello:thisweirdtrick
等等,这样就可以直接使用命令 docker images hello
列出所有镜像名为 hello 的镜像,不会被其他镜像所干扰。
2. 多阶段构建
要想大幅度减少镜像的体积,多阶段构建是必不可少的。多阶段构建的想法很简单:“我不想在最终的镜像中包含一堆 C 或 Go 编译器和整个编译工具链,我只要一个编译好的可执行文件!”
多阶段构建可以由多个 FROM
指令识别,每一个 FROM
语句表示一个新的构建阶段,阶段名称可以用 AS
参数指定,例如:
FROM gcc AS mybuildstage
COPY hello.c .
RUN gcc -o hello hello.c
FROM ubuntu
COPY --from=mybuildstage hello .
CMD ["./hello"]
本例使用基础镜像 gcc
来编译程序 hello.c
,然后启动一个新的构建阶段,它以 ubuntu
作为基础镜像,将可执行文件 hello
从上一阶段拷贝到最终的镜像中。最终的镜像大小是 64 MB
,比之前的 1.1 GB
减少了 95%
:
两个奇技淫巧,将 Docker 镜像体积减小 99%的更多相关文章
- 如何合并两个Docker 镜像
http://www.open-open.com/lib/view/open1437746544709.html 在你的机器上使用docker pull来从Docker Hub下载镜像. docker ...
- Docker镜像构建的两种方式(六)--技术流ken
镜像构建介绍 在什么情况下我们需要自己构建镜像那? (1)当我们找不到现有的镜像,比如自己开发的应用程序 (2)需要在镜像中加入特定的功能 docker构建镜像有两种方式:docker commit命 ...
- 构建Docker镜像两种方式的比较-Dockerfile方式和S2I方式
前言 写Dockerfile是构建Docker镜像最通常的方式,接触过Docker的童鞋多少了解一些.前段时间研究OpenShift(paas的一种),发现了另外一种构建Docker镜像的方式:S2I ...
- 制作Docker镜像的两种方式
此文已由作者朱笑天授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 一.使用docker commit命令制作docker镜像 1. pull一个centos6.6的基础镜像, ...
- [转] 构建Docker镜像两种方式的比较-Dockerfile方式和S2I方式
原文地址:https://www.cnblogs.com/tianshifu/p/8127837.html 前言 写Dockerfile是构建Docker镜像最通常的方式,接触过Docker的童鞋多少 ...
- Docker镜像构建的两种方式(六)
镜像构建介绍 在什么情况下我们需要自己构建镜像那? (1)当我们找不到现有的镜像,比如自己开发的应用程序 (2)需要在镜像中加入特定的功能 docker构建镜像有两种方式:docker commit命 ...
- 两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库
两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库 1.GitHub Actions 是什么? 大家知道,持续集成由很多操作组成,比如抓取代码.运行测试. ...
- springboot整合docker部署(两种构建Docker镜像方式)--2019-3-5转
原文:https://www.cnblogs.com/shamo89/p/9201513.html 项目结构 package hello; import org.springframework.boo ...
- springboot整合docker部署(两种构建Docker镜像方式)
项目结构 package hello; import org.springframework.boot.SpringApplication; import org.springframework.bo ...
随机推荐
- 转: zabbix对cisco2960的监控
转自:http://blog.chinaunix.net/uid-12115233-id-3561954.html 1:首先在官网下载Cisco2950 模板https://www.zabbix.co ...
- Dungeon Master (三维BFS)
题目: You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed o ...
- numpy的索引
import numpy as np A =np.arange(3,15).reshape(3,4) print(A) #第一行 print(A[2]) #返回元素 print(A[1][2]) pr ...
- Python如何规避全局解释器锁(GIL)带来的限制
编程语言分类概念介绍(编译型语言.解释型语言.静态类型语言.动态类型语言概念与区别) https://www.cnblogs.com/zhoug2020/p/5972262.html Python解释 ...
- this.props
React中的每一个组件,都包含有一个属性(props),属性主要是从父组件传递给子组件的,在组件内部,我们可以通过this.props获取属性对象
- RocketMQ 单机版安装并测试
一.安装maven 1.下载maven,http://maven.apache.org/download.cgi,并解压: -bin.tar.gz 2.修改系统环境变量,并验证: vim /etc/p ...
- 换到GitHub 博客了
觉得还是github上面的代码风格看起来舒服些,所以决定把blog搬到github上面去了.以后这里就作为一个放资料的地方吧. github地址:http://l34rner.github.io/
- brup安装证书抓取https
brup安装证书抓取https 0x00下载 下载安装brup 前提是需要java环境 0X01配置brup 配置brup的代理设置 0X02设置浏览器 我使用的是火狐,以下都以火狐为例 0X03证书 ...
- Cenots 7 通过Yum 安装Node.js 报错问题
环境:CentOS Linux release 7.3.1611 (Core) 安装报错信息: [cenots7@localhost ~]$ sudo yum -y install npm Loade ...
- (原)人体姿态识别PyraNet
转载请注明出处: https://www.cnblogs.com/darkknightzh/p/12424767.html 论文: Learning Feature Pyramids for Huma ...