原文链接:Docker Images : Part I - Reducing Image Size

对于刚接触容器的人来说,他们很容易被自己构建的 Docker 镜像体积吓到,我只需要一个几 MB 的可执行文件而已,为何镜像的体积会达到 1 GB 以上?本文将会介绍几个奇技淫巧来帮助你精简镜像,同时又不牺牲开发人员和运维人员的操作便利性。本系列文章将分为三个部分:

第一部分着重介绍多阶段构建(multi-stage builds),因为这是镜像精简之路至关重要的一环。在这部分内容中,我会解释静态链接和动态链接的区别,它们对镜像带来的影响,以及如何避免那些不好的影响。中间会穿插一部分对 Alpine 镜像的介绍。

第二部分将会针对不同的语言来选择适当的精简策略,其中主要讨论 Go,同时也涉及到了 JavaNodePythonRubyRust。这一部分也会详细介绍 Alpine 镜像的避坑指南。什么?你不知道 Alpine 镜像有哪些坑?我来告诉你。

第三部分将会探讨适用于大多数语言和框架的通用精简策略,例如使用常见的基础镜像、提取可执行文件和减小每一层的体积。同时还会介绍一些更加奇特或激进的工具,例如 BazelDistrolessDockerSlimUPX,虽然这些工具在某些特定场景下能带来奇效,但大多情况下会起到反作用。

本文介绍第一部分。

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:gcchello:ubuntuhello: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%的更多相关文章

  1. 如何合并两个Docker 镜像

    http://www.open-open.com/lib/view/open1437746544709.html 在你的机器上使用docker pull来从Docker Hub下载镜像. docker ...

  2. Docker镜像构建的两种方式(六)--技术流ken

    镜像构建介绍 在什么情况下我们需要自己构建镜像那? (1)当我们找不到现有的镜像,比如自己开发的应用程序 (2)需要在镜像中加入特定的功能 docker构建镜像有两种方式:docker commit命 ...

  3. 构建Docker镜像两种方式的比较-Dockerfile方式和S2I方式

    前言 写Dockerfile是构建Docker镜像最通常的方式,接触过Docker的童鞋多少了解一些.前段时间研究OpenShift(paas的一种),发现了另外一种构建Docker镜像的方式:S2I ...

  4. 制作Docker镜像的两种方式

    此文已由作者朱笑天授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 一.使用docker commit命令制作docker镜像 1. pull一个centos6.6的基础镜像, ...

  5. [转] 构建Docker镜像两种方式的比较-Dockerfile方式和S2I方式

    原文地址:https://www.cnblogs.com/tianshifu/p/8127837.html 前言 写Dockerfile是构建Docker镜像最通常的方式,接触过Docker的童鞋多少 ...

  6. Docker镜像构建的两种方式(六)

    镜像构建介绍 在什么情况下我们需要自己构建镜像那? (1)当我们找不到现有的镜像,比如自己开发的应用程序 (2)需要在镜像中加入特定的功能 docker构建镜像有两种方式:docker commit命 ...

  7. 两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库

    两种github action 打包.Net Core 项目docker镜像推送到阿里云镜像仓库 1.GitHub Actions 是什么? 大家知道,持续集成由很多操作组成,比如抓取代码.运行测试. ...

  8. springboot整合docker部署(两种构建Docker镜像方式)--2019-3-5转

    原文:https://www.cnblogs.com/shamo89/p/9201513.html 项目结构 package hello; import org.springframework.boo ...

  9. springboot整合docker部署(两种构建Docker镜像方式)

    项目结构 package hello; import org.springframework.boot.SpringApplication; import org.springframework.bo ...

随机推荐

  1. 吴裕雄--python学习笔记:os模块的使用

    在自动化测试中,经常需要查找操作文件,比如说查找配置文件(从而读取配置文件的信息),查找测试报告(从而发送测试报告邮件),经常要对大量文件和大量路径进行操作,这就依赖于os模块. 1.当前路径及路径下 ...

  2. The Process class relies on proc_open, which is not available on your PHP installation报错解决

    同事laravel框架开发的代码有如下错误日志 production.ERROR: The Process class relies on proc_open, which is not availa ...

  3. XML的四种解析器(dom_sax_jdom_dom4j)原理及性能比较[收藏]

    1)DOM(JAXP Crimson解析器)    DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定 ...

  4. Uber刷单,刷出中国的人性劣根?

         美国叫车应用Uber国际化之路一直挺顺利的,融资也挺顺利的,他们现在很有钱,最新总融资金额达到100亿美元,创下美国非上市高科技公司的融资纪录.全新的商业模式,以及优质的客户体验,让Uber ...

  5. figure图像

    import matplotlib.pyplot as plt import numpy as np x=np.linspace(-3,3,50) y1=x*2+1 y2=x**2 plt.plot( ...

  6. React Docs(1)

    安装 React在codepen上提供了一个Hello,World项目事例,只需打开网站,即可尝试React.另外还提供了一个html文件的Hello,World项目,项目中引用CDN的react.j ...

  7. 微信小程序入门讲解

    微信小程序 注册 由于发文限制,请自行到微信公众平台注册 项目结构 project.config.json 配置文件(不需要动) app.json(用户配置) 路由pages window 整个程序样 ...

  8. jdbc里一个最靠谱的连接demo

    最靠谱的jdbc连接例子 包括增删改,查一条数据,查所有数据. Bean.java public class Bean { private String id; private String numb ...

  9. 常用css3选择器

    <div class="wrapper"> <p class="test1">1</p> <p class=" ...

  10. VueX状态管理器 的应用

    VueX状态管理器 cnpm i vuex axios -S 1 创建Vuex 仓库 import Vue from 'vue' import Vuex from 'vuex' vue.use(Vue ...