如何 build 出尽可能小的 docker image?

1. 简介

我们自己构建 Docker image 时都希望结果镜像越小越好,那么如何才能尽量变小呢?

下面我们通过一个简单的案例,了解下优化思路,看一个简单的镜像如何从 743MB 减到 536MB

2. 案例

目标

非常简单,build 一个 java 镜像

基于 centos 基础镜像,和下载好的 jdk-8u101-linux-x64.tar.gz

过程

1)第一版

Dockerfile 内容:

FROM centos

COPY jdk-8u101-linux-x64.tar.gz /usr/local/
WORKDIR /usr/local
RUN tar -zxf /usr/local/jdk-8u101-linux-x64.tar.gz && rm /usr/local/jdk-8u101-linux-x64.tar.gz

ENV JAVA_HOME /usr/local/jdk1.8.0_101
ENV PATH $JAVA_HOME/bin:$PATH

build 后镜像大小为:743 MB

centos 基础镜像的大小是 197MB,jdk 压缩包是 173MB,而最终结果 743MB 有点太大了

这个 Dockerfile 的问题在于:虽然 tar 解压之后立即使用 rm 删除了压缩包,但与上面的 COPY 不在一层,所以删了也无法减小最终的体积

2)第二版

为了解决上一版中压缩包的问题,可以使用 ADD 命令,直接把解压后的内容放入镜像,而不是把压缩包放入进行内再解压

FROM centos

ADD jdk-8u101-linux-x64.tar.gz /usr/local/

ENV JAVA_HOME /usr/local/jdk1.8.0_101
ENV PATH $JAVA_HOME/bin:$PATH

build 后镜像大小为:562 MB,少了压缩包的大小,这样就好了很多

如果压缩包不在本地,需要通过网络下载,然后解压,那么就要让 下载、解压、删除 这3个动作在同一层操作,例如:

RUN wget http://xxx.com/app && tar -xzf app.tar.gz && rm app.tar.gz

这样就可以避免压缩包占用镜像空间

3)第三版

上一版已经很简洁了,还有什么可以优化的呢?

我们先在本地把 jdk-8u101-linux-x64.tar.gz 解压看一下

解压后目录是 jdk1.8.0_101,大小 352M

进入目录可以看到 javafx-src.zip(4.9M) 和 src.zip(21M) 这两个源码包文件,我们在实际环境中可能并不需要他们,那么拷贝到镜像中就比较多余了

Docker 有一个过滤功能,可以让我们排除掉不需要的文件,方法是编写 .dockerignore 文件

Dockerfile内容:

FROM centos

COPY jdk1.8.0_101 /usr/local/jdk1.8.0_101

ENV JAVA_HOME /usr/local/jdk1.8.0_101
ENV PATH $JAVA_HOME/bin:$PATH

.dockerignore内容:

*/*.zip

位置关系:

├── .dockerignore
├── Dockerfile
└── jdk-8u101-linux-x64.tar.gz

build 后镜像大小为:536 MB,比第一版的 743MB 少了 207MB

.dockerignore 的作用很大,一般的开源项目包中会有源码、文档,例如 hadoop 包中的 doc 就有 96MB,还有我们自己项目中也可能会有不必要的文件,例如 .git.svntmp 等等,都可以通过 .dockerignore 进行排除

3. 小结

上面的案例中,优化的思路就是尽量少往镜像里放东西

还有一点比较重要,一定要选用最合适的基础镜像,例如:

  1. 可以看看只有 5MB 的 alpine 镜像是否能满足自己的需求,ubuntu、centos 这些基础镜像都是100多MB的,如果能使用 alpine 那么就减小了很多
  2. 通常公司内会构建自己的基础镜像,例如构建一个 Ruby+Rails+... 通用镜像,需要其他镜像时就以此为基础,但如果有的 service 只需要 Ruby 而不要 Rails 等其他东西,这时就多余了,有精力的话可以把基础镜像拆分得更细一些

原文发布于微信公众号 - 性能与架构(yogoup)

原文发表时间:2017-03-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小狼的世界

Docker 概述

Docker 是一个应用程序开发、部署、运行的平台,使用 go 语言开发。相较于传统的主机虚拟化,Docker 提供了轻量级的应用隔离方案,并且为我们提供了应用...

12530
来自专栏散尽浮华

Docker容器学习梳理--基础知识(1)

Docker是PaaS 提供商 dotCloud 开源的一个基于 LXC 的高级容器引擎,源代码托管在 Github 上, 基于go语言并遵从Apache2.0...

320100
来自专栏北京马哥教育

Docker Swarm学习笔记(一)

Docker Swarm概述 Docker Swarm是Docker官方提供的集群工具。它可以将一些关联的Docker主机转变成一个虚拟Docker主机。因为D...

33350
来自专栏吴伟祥

Docker学习——创建镜像(四) 顶

15040
来自专栏搜云库

Ubuntu 17.04 x64 安装 Docker CE 初窥 Dockerfile 部署 Nginx

Docker 是个划时代的开源项目,它彻底释放了计算虚拟化的威力,极大提高了应用的运行效率,降低了云计算资源供应的成本!使用 Docker,可以让应用的部署、测...

25260
来自专栏Rainbond开源「容器云平台」

Dockerfile,你给我站住!

15650
来自专栏zingpLiu

Docker快速入门(二)

上篇文章《Docker快速入门(一)》介绍了docker的基本概念和image的相关操作,本篇将进一步介绍image,容器和Dockerfile。

13830
来自专栏圣杰的专栏

Hello Docker

Docker: Build, Ship, and Run Any App, Anywhere 在任何地方构建、交付和运行任何应用 1. 引言 最近简单的学...

25790
来自专栏北京马哥教育

5个你必须知道的Docker实用工具

原文:5 Docker Utilities You Should Know 作者:Shekhar Gulati 翻译:Vincent Docker社区已经创建了...

39490
来自专栏Felix的技术分享

Docker简单使用

259110

扫码关注云+社区

领取腾讯云代金券