本文的原文地址是 What constitutes a good docker image?node
注:本文不會所有翻譯,只會挑選我的認爲有價值的部分進行摘取性翻譯,如想詳細閱讀,請看原文python
在撰寫本文時,ubuntu:14.04
爲 195 MB,然而 debian:wheezy
是 85 MB,可是 Ubuntu 額外的幾百兆字節不會給你帶來任何價值(我所知道的)。在一些極端狀況下,甚至可能你的基礎鏡像是 2 MB busybox
。這可能僅僅其實是二進制包的靜態鏈接。linux
構建工具佔用太多空間,而且從源碼構建一般很慢。若是你只是安裝別人的軟件,一般不須要從源碼構建,而且它應該被避免。好比,沒有必要安裝 python,gcc 等等。爲了獲取最新版本的 node.js 並運行在一臺 Debian 主機上。在 node.js downloads page 這裏有一個可用的二進制的壓縮包。相似的,redis 能夠經過包管理器安裝。git
至少有幾個很好的理由使用構建工具:github
npm install
安裝一些模塊來編譯進二進制包在第二種狀況下,好好的想清楚,你是否真應該這樣作。在第三種狀況下,我建議在另一個 "npm installer" 鏡像安裝構建工具,基於最小的 node.js 鏡像。redis
下面的 Dockerfile
結果鏡像大小是 109 MB:docker
FROM debian:wheezy RUN apt-get update && apt-get install -y wget RUN wget http://cachefly.cachefly.net/10mb.test RUN rm 10mb.test
在另外一方面,這看似至關的 Dockerfile
結果鏡像大小是 99 MB:npm
FROM debian:wheezy RUN apt-get update && apt-get install -y wget RUN wget http://cachefly.cachefly.net/10mb.test && rm 10mb.test
所以看起來若是你在 Dockerfile
的兩個步驟之間在磁盤空間留下了一個文件,當你刪除這個文件的時候,空間不會被回收。也能夠徹底避免臨時文件,僅僅在命令行之間管道輸出。好比:ubuntu
wget -O - http://nodejs.org/dist/v0.10.32/node-v0.10.32-linux-x64.tar.gz | tar zxf -
將提取壓縮文件,並無把它放在文件系統上。緩存
若是你運行 apt-get update
設置你的容器,它在 /var/lib/apt/lists/
目錄構成了數據,可是一旦鏡像完成,這些數據是不須要的。你能夠安全的清理那個目錄來節約一些兆字節。
這個 Dockerfile
生成一個 99 MB 鏡像:
FROM debian:wheezy RUN apt-get update && apt-get install -y wget
然而這個生成一個 90 MB 的鏡像:
FROM debian:wheezy RUN apt-get update && apt-get install -y wget && rm -rf /var/lib/apt/lists/*
當一個 Docker 鏡像是不可變的,一個 Dockerfile
是不保證在運行在不一樣的時間生成相同的輸出。這個問題,固然,是外部狀態,而且咱們難以控制它。最好在某種程度上最小化你的 Dockerfile
外部狀態的影響,這是有可能的。作這個的一個簡單方式是指定包的版本,當經過包管理器更新的時候。這裏有一個怎樣作的示例:
# apt-get update # apt-cache showpkg redis-server Package: redis-server Versions: 2:2.4.14-1 ... # apt-get install redis-server=2:2.4.14-1
咱們所能但願的是,可是這是沒有保障的,包倉庫從如今開始的一年仍然會是這個版本。儘管如此,明確的顯示你鏡像中依賴的軟件版本是不能否認的價值。
若是你有一系列的相關命令,最好的方式是在一個命令中串聯它們。這是一個更有意義的構建緩存(邏輯分組步驟集中到一個緩存步驟)並使得文件系統層級數量降下來了(我認爲一般這是可取的,可是不知道在客觀上是不是更好的)。
反斜線符號 \
在這裏幫助你提高可讀性:
RUN apt-get update && \ apt-get install -y \ wget=1.13.4-3+deb7u1 \ ca-certificates=20130119 \ ...
這是我閱讀官方的 node.js Docker 鏡像的 Dockerfile 學來的一個技巧。此外,這個 Dockerfile
是很是棒的。我惟一的指責就是它是基於一個巨大的 buildpack-deps 鏡像,帶着各類各樣我不須要或不想要的東西。
你可使用 ENV
定義環境變量,而後在一系列的命令中引用它們。下面,我從連接的 Dockerfile
中轉述了摘要:
ENV NODE_VERSION 0.10.32 RUN curl -SLO "http://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" \ && tar -xzf "node-v$NODE_VERSION-linux-x64.tar.gz" -C /usr/local --strip-components=1 \ && rm "node-v$NODE_VERSION-linux-x64.tar.gz"
上面這個版本信息,你只須要使用環境變量 NODE_VERSION
定義一次便可,而不用每次都寫。