怎樣構建一個好的 Docker 鏡像

本文的原文地址是 What constitutes a good docker image?node

注:本文不會所有翻譯,只會挑選我的認爲有價值的部分進行摘取性翻譯,如想詳細閱讀,請看原文python

構建一個好的 Docker 鏡像

debian 的基礎鏡像

在撰寫本文時,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

  • 你須要一個指定的版本(好比,在 Debian 倉庫,redis 版本太老)
  • 你須要使用指定的選項編譯
  • 你須要 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 定義一次便可,而不用每次都寫。

相關文章
相關標籤/搜索