微容器:更小的,更轻便的Docker容器

【编者的话】本文介绍了微容器的概念和好处,并用一些例子介绍了如何构建微镜像,从scratch到Alpine Linux,并推荐了一些已有的基础微镜像,方便为几乎全部主流语言的应用构建微镜像。本文也指出了构建微镜像的基本原理:将构建时依赖和运行时依赖分开,构建时所用的镜像包含全部构建所用的工具,它能够比较大,但运行时的基础镜像应该仅包含运行时依赖。使用微容器,no going back!node



Docker 使你能把你的应用和应用的依赖打包到一个良好的自包含镜像中。而后你能够用该那个镜像来在容器中运行你的应用。问题是,你一般也打包了一些你可能不须要比你须要的更多的东西,最终座椅最重你获得了一个巨大的镜像和巨大的容器。大多数开始使用Docker的人会使用Docker的官方仓库做为他们的语言的选择,可是不幸的是,若是你使用官方镜像,你会获得一个巨大的镜像,而原本你能够获得一个小镜像的。你并不须要和这些官方镜像中一块儿的许多复杂的东西。例如,若是你使用官方的Node镜像构建一个你的应用的Node的镜像,它至少有643MB大,由于这是官方Node镜像的大小

我构建了一个简单的Hello World Node 应用,在官方Node镜像上构建,它的大小是644MB。
git


这太大了!个人应用加上依赖也不超过1MB,Node.js的运行时大概20MB,那是什么占据了剩下的620MB?咱们应该能作得更好。
github


什么是微容器?


一个微容器仅包含OS库和运行应用所须要的语言依赖以及应用自己。其余都不须要。

与其包含全部,不如仅包含最基本的,在须要的时候添加依赖。

以上面的Node应用为例,使用一个小的基础镜像,而后安装核心的部分,即Node.js和它的依赖,它只有29MB,小了22倍(见下图)!
golang




若是你想,如今试试运行这两个镜像,docker run –rm -p 8080:8080 treeder/tiny-node:fat 而后 docker run –rm -p 8080:8080 treeder/tiny-node:latest。彻底同样的应用,而大小大不相同。
docker


为何微容器很棒?


有许多使用微容器的好处:
npm

  • 大小 —— 微容器很小。像上面展现的,没有改变任何代码,镜像大小减小了22倍。后端

  • 快速/简单的发布 —— 由于镜像很是小,能够更快地从 Docker registry(例如 Docker Hub)下载镜像,于是能够更快地发布到不一样的机器。安全

  • 提升安全性 —— 更少的代码和程序在容器中意味着更小的攻击面。基础OS就更安全(详见下文)。app


这些好处和Unikernels的好处相似,没有任何缺点。
工具


如何构建微容器


全部Docker镜像的基础镜像是scratch镜像。它本质上什么都没有。听起来它好像没什么无用,可是你能够用它建立你的应用的最小可能镜像,若是你把你的应用编译为一个没有依赖的静态二进制文件,像Go或C那样。例如,个人treeder/static-go 镜像 包含了一个Go的Web应用,则整个镜像(包括个人应用)是5MB。


这是关于如何获得尽量小的镜像:scratch镜像+你的应用的二进制文件。

然而并非全部人都是用Go,因此你可能有更多的依赖,而且你须要比scratch镜像要多一些的东西。关于Alpine Linux,我不会枯燥地告诉你关于它的细节,可是他们的广告语说出了所有:“Alpine Linux是一个面向安全的,轻量的Linux发行版,基于musl libc和busybox。” 你能够在这里获得详细说明,可是咱们这篇文章最关心的是“轻量”的部分。基础的Alpine镜像只有5MB。


如今咱们有一个很是好的OS做为一个基础镜像,它有一个很好的包管理系统来添加咱们的依赖。对于咱们的简单的Node应用而言,咱们只须要Node本身,因此咱们能够只添加Node包。咱们的Dockerfile看起来像这样:

FROM alpine
RUN apk update && apk upgrade
RUN apk add nodejs


简单而整洁。如今咱们只在镜像中有Node和Node的依赖。
如今为了添加咱们的代码到镜像中,只须要在咱们的Dockerfile中添加几行:

FROM alpine
RUN apk update && apk upgrade
RUN apk add nodejs
WORKDIR /app
ADD . /app
ENTRYPOINT [ "node", "server.js" ]


你能够得到示例代码而且在这里(https://github.com/treeder/tiny-node-docker)查看完整的构建指导。

一样的规则适用于全部其余的语言。


适用于全部语言的基础镜像


幸运的是,咱们已经构建了一个适用全部主要语言的基础镜像,你能够在这里找到它们:https://github.com/iron-io/dockers

它们有一些优化来使它们尽量的小,而且咱们会按期更新,使用基础镜像使得它们比起你本身来更好。经过使用Iron.io的基础镜像,上面Node应用的Dockerfile变成这样:

FROM iron/node
WORKDIR /app
ADD . /app
ENTRYPOINT [ "node", "server.js" ]


另外,对于每一种其余语言,咱们构建了两个版本的这种镜像,一个用于构建,另外一个用于运行。用于构建的镜像有全部的构建工具在其中,因此可能比运行时要更大。

例如,为了构建Node的依赖,你要像这样使用iron/node:dev

docker run --rm -v "$PWD":/app -w /app iron/node:dev npm install


而后在你的Dockerfile中使用iron/node而后运行它:

docker run --rm -it -p 8080:8080 -v "$PWD":/app -w /app iron/node node server.js


上述方法一样适用于其余语言,可是你须要使用它们本身的build/vendor/run的指令。

若是你想要一个语言的不一样版本,你能够改变tag,例如你可使用iron/node:4.1或者iron/node:0.12。你能够在Docker Hub上找到每一个语言的全部的版本tag。例如Node的tag在这里:https://hub.docker.com/r/iron/node/tags/。你能够在iron-io/dockers的项目里找到全部其余Docker Hub tags的连接。


如何为全部的语言构建和打包


这可能没那么幸运了,可是咱们有一些例子可让大多数主流语言使用上面的基础镜像:https://github.com/iron-io/dockerworker

你能够看看那个项目中的每一个语言的README,它会指引你如何构建你的依赖,测试你的代码,构建一个小的Docker镜像和测试镜像。


没有回头


读完本文以后,你应该能够为你的应用建立只包含运行应用所须要的东西的Docker镜像。容器本质是一个镜像的实例,因此一旦你开始用你的镜像来运行容器,你就进入了微容器的世界。没有(理由)回头。

刚使用了你的“小镜像”技术在个人一个golang项目上,很棒!感谢这篇伟大的文章。居然使人震惊地减少到5mb。 —— Harlow Ward @ Clearbit

原文连接:Microcontainers – Tiny, Portable Docker Containers (翻译:陈光 审校:高婧雅)



关于阿里百川

阿里百川(baichuan.taobao.com)是阿里巴巴集团“云”+“端”的核心战略是阿里巴巴集团无线开放平台,基于世界级的后端服务和成熟的商业组件,经过“技术、商业及大数据”的开放,为移动创业者提供可快速搭建App、商业化APP并提高用户体验的解决方案;同时提供多元化的创业服务-物理空间、孵化运营、创业投资等,为移动创业者提供全面保障。

相关文章
相关标签/搜索