【編者的話】本文介紹了微容器的概念和好處,並用一些例子介紹瞭如何構建微鏡像,從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並提高用戶體驗的解決方案;同時提供多元化的創業服務-物理空間、孵化運營、創業投資等,爲移動創業者提供全面保障。