Docker 最佳实践:构建最小镜像

标签: dev | 发表时间:2018-06-27 00:00 | 作者:
出处:http://itindex.net/relian

镜像大小其实是衡量我们容器打包技术的重要指标,我们应该在不影响应用正常运行的情况下,尽量让我们的容器镜像变得更小,这样,不管是从安全还是维护效率角度来讲,都是最佳实践。

本文我们从两种情况阐述我们的问题和解决方案,我们从实现我们的application的编程语言角度,按照语言是解释型还是编译型语言来演示如何解决容器镜像体积大的问题。

解释型语言

大部分的脚本语言都是解释型语言,像Ruby,Python,PHP等,我们只需要把我们的代码扔给解释器,解释器去运行就好了,但是这里的解释器有大有小,为什么?

首先Docker为一些“懒人”准备了一种Docker Image,比如Python,那么我们可以非常方便的从DockerHub上拉取某一个版本的Python镜像,比如Python3。6

   
  1. $ docker image ls

  2. python 3.6.5 a5b7afcfdcc8 2 weeks ago 912MB

  3. python 3.6.5-alpine 27e79c0fa4d2 2 months ago 87.4MB

我们会看到,同样是3.6.5, alpine linux的docker image就小了非常非常多,是普通的python3.6.5十分之一大小,为什么呢?主要是因为为了照顾“懒人”,Python:3.6.5 image预先安装了大量python的工具和编译的头文件等,包括C的编译环境等等。

而python:3.6.5-alpine 基本上除了Linux系统必须的一些文件以外,基本只包含基本的Python运行环境,例如像  gcc 等工具是不会预先安装的,都是用户需要的时候自行安装。

所以进一步来讲,我们要打包我们的Python应用,使用以上这两种base image的效果就显而易见了,一个打包完的image会上G大小,另一个只有100M左右。

例如下面是一个python flask的Dockerfile

   
  1. FROM python:3.6-alpine

  2. LABEL maintainer="XYZ <xxx@xxx.com>"

  3. RUN apk add --no-cache gcc musl-dev

  4. COPY . /app

  5. WORKDIR /app

  6. RUN pip install -r requirements.txt

  7. EXPOSE 8000

  8. CMD []

编译型语言

使用编译型语言(例如C,Go等)编写的应用程序打包成Docker镜像,这里面的优化空间就更大了,我们以Go语言为例。

假如我们有一个Go APP,假如使用普通的go image,那么我们构建出来的镜像会很大,例如这个app https://github.com/golang/example/blob/master/outyet/Dockerfile

   
  1. FROM golang:onbuild

  2. EXPOSE 8080

构建完的docker image 700多M。

   
  1. $ docker images go-demo

  2. REPOSITORY TAG IMAGE ID CREATED SIZE

  3. go-demo latest f562d6efa39c 21 seconds ago 707MB

然后利用前面我们讲的,我们可以替换base image,选择一个alpine的base image,例如:

   
  1. FROM golang:alpine

  2. WORKDIR /app

  3. ADD . /app

  4. RUN cd /app && go build -o goapp

  5. EXPOSE 8080

  6. ENTRYPOINT ./goapp

构建的image,只有不到400M。

   
  1.  $ docker images go-demo

  2. REPOSITORY TAG IMAGE ID CREATED SIZE

  3. go-demo latest f562d6efa39c 3 minutes ago 707MB

  4. $ docker images go-demo-alpine

  5. REPOSITORY TAG IMAGE ID CREATED SIZE

  6. go-demo-alpine latest a16d2986dbd1 9 seconds ago 385MB

但是,我们还可以让我们的image变得更小。根据我们之前讲的分阶段build,我们可以分阶段build我们的APP,然后最终只需要在一个很小的image里,运行我们程序编译后的结果即可,例如

   
  1. FROM golang:alpine AS build-env

  2. WORKDIR /app

  3. ADD . /app

  4. RUN cd /app && go build -o goapp

  5. FROM alpine

  6. RUN apk update && \

  7.  apk add ca-certificates && \

  8.  update-ca-certificates && \

  9.  rm -rf /var/cache/apk/*

  10. WORKDIR /app

  11. COPY --from=build-env /app/goapp /app

  12. EXPOSE 8080

  13. ENTRYPOINT ./goapp

这样,又能省掉一部分空间。只有13M,惊不惊喜!!!

   
  1. $ docker images go-demo-muti-build

  2. REPOSITORY TAG IMAGE ID CREATED SIZE

  3. go-demo latest f562d6efa39c 3 minutes ago 707MB

  4. go-demo-alpine latest a16d2986dbd1 9 seconds ago 385MB

  5. go-demo-muti-build latest 1b1237a8fe0e 20 seconds ago 13.5MB

总结

所以,我们每次build自己的docker image的时候,一定要思考一下,怎么才能让我们的docker image变得更加小巧,更小的image其实也是更安全的,因为冗余的软件包少,那么漏洞就相应的少,另外小的docker image方便移动,不管是docker push还是pull,速度都很快。

快看一看自己手头上的docker image,有没有优化的空间吧!


相关 [docker 最佳实践 镜像] 推荐:

Docker 最佳实践:构建最小镜像

- - IT瘾-dev
镜像大小其实是衡量我们容器打包技术的重要指标,我们应该在不影响应用正常运行的情况下,尽量让我们的容器镜像变得更小,这样,不管是从安全还是维护效率角度来讲,都是最佳实践. 本文我们从两种情况阐述我们的问题和解决方案,我们从实现我们的application的编程语言角度,按照语言是解释型还是编译型语言来演示如何解决容器镜像体积大的问题.

Docker 最佳实践:5 个方法精简镜像

- - IT瘾-dev
本文记录了精简Docker镜像尺寸的必要性及好处. 上篇文章回顾: HBase实战:记一次Safepoint导致长时间STW的踩坑之旅. 精简Docker镜像的好处很多,不仅可以节省存储空间和带宽,还能减少安全隐患. 优化镜像大小的手段多种多样,因服务所使用的基础开发语言不同而有差异. 本文将介绍精简Docker镜像的几种通用方法.

Docker镜像仓库Harbor

- - 灰狐博客
Habor是由VMWare公司开源的容器镜像仓库. Habor是在Docker Registry上进行了相应的企业级扩展,这些企业级特性包括:管理用户界面,基于角色的访问控制 ,AD/LDAP集成以及审计日志等. 京东使用了Harbor搭建了自己的私有Dockr镜像仓库. 用Harbor实现容器镜像仓库的管理和运维.

几款 Shadowsocks 的 Docker 镜像

- - Shadowsocks非官方网站
Docker 是一个开放源代码软件项目,让应用程序布署在软件容器下的工作可以自动化进行,借此在 Linux 操作系统上,提供一个额外的软件抽象层,以及操作系统层虚拟化的自动管理机制. Docker 利用 Linux 核心中的资源分脱机制,例如 cgroups,以及 Linux 核心名字空间(name space),来创建独立的软件容器(containers).

mdblog/Docker镜像中心.md at master · downgoon/mdblog · GitHub

- -
手把手体验DockerHelloWorld. Docker Image: 它是用来运行出. Docker Container的. nodejs image等. Docker Registry Mirrors: 为了让大家方便使用,不需要每个人都去制作. Docker Image,我们可以分享:你制作一个.

docker/kubernetes国内源/镜像源解决方式

- - Xinkun Blog
最近在使用kubeadm时,被各种连接不上搞到崩溃. 这里统一整理了国内的一些镜像源,apt源,kubeadm源等,以便查阅. Azure China提供了目前用过的质量最好的镜像源. 而且都支持匿名拉取,也就是不需要登录. 这里,我开发了一个小的脚本azk8spull,这个脚本可以自动根据镜像名称进行解析,转换为azure的mirror镜像源域名.

Docker & Flatpak

- - IT瘾-dev
目前最流行的技术莫过于Docker,Docker和Docker衍生的东西用到了很多很酷的技术,目前deepin应用软件发布转变成flatpak,这些看似风牛马不相及的技术方案,实际都使用了一个共同的底层技术——Namespace,假如没有namespace支持,这些技术实现都将成为空中楼阁. 一句话总结,无论是Docker、sysmted-nspawn还是flatpak,都是在namespace基础上,针对不同的场景,生出的不同的解决方案.

jQuery最佳实践

- andi - 阮一峰的网络日志
上周,我整理了《jQuery设计思想》. 那篇文章是一篇入门教程,从设计思想的角度,讲解"怎么使用jQuery". 今天的文章则是更进一步,讲解"如何用好jQuery". 我主要参考了Addy Osmani的PPT《提高jQuery性能的诀窍》(jQuery Proven Performance Tips And Tricks).

PHP最佳实践

- xiangqian - 阮一峰的网络日志
虽然名字叫《PHP最佳实践》,但是它主要谈的不是编程规则,而是PHP应用程序的合理架构. 它提供了一种逻辑和数据分离的架构模式,属于MVC模式的一种实践. 我觉得,这是很有参考价值的学习资料,类似的文章网上并不多,所以一边学习,一边就把它翻译了出来. 根据自己的理解,我总结了它的MVC模式的实现方式(详细解释见译文):.

MongoDB最佳实践

- - NoSQLFan
将 MongoDB加入到我们的服务支持列表中,是整个团队年初工作计划中的首要任务. 但我们感觉如果先添加一项对NoSQL存储的支持,而不是先升级已支持的关系型数据库,可能对用户不太好,毕竟目前的用户都使用关系型数据库. 所以我们决定将引入MongoDB这项工作放到升级MySQL和PostgreSQL之后来做.