用 Dockerfile 構建 docker image

view

   dockerfile是爲快速構建docker image而設計的,當你使用docker build 命令的時候,docker 會讀取當前目錄下的命名爲Dockerfile(首字母大寫)的純文本文件並執行裏面的指令構建出一個docker image。

  而另一種構建docker iamge 的方法是pull一些基礎鏡像下來啓動成容器,然後進入容器內安裝各種需要的程序以及配置好需要的環境,最後commit成一個鏡像。但是相比之 Dockerfile的方法會更加自動化,更加方便快捷,而且功能也更強大。(Docker build方法底層裏也是在基礎鏡像下啓動容器然後commit的,但是這些不需要我們手動去commit以及rm,都是自動化的。)

 

======(注:以下大部分內容均參考自官方文檔)

首先,是關於構建docker image的一些優化建議

我們希望構建出的image對應的容器應該是可以在服務羣中暫停(解耦性)並且快速替換,這要求容器可以在極短的時間內完成啓動並配置運行起來。

優化手段:

 

 使用.dockerignore文件 .

dockerignore文件的設計是爲了在docker build的過程中排除不需要用到的文件以及目錄,目的是爲了docker build這個過程可以儘可能地快速高效以及構建出來的image沒有多餘的“垃圾”。

 

不要安裝不必要的程序包

我們希望構建出來的image儘可以的輕小、依賴性小以及構建過程儘可能地快。這就需要你在構建的時候不要安裝不必要的程序,例如,一個存儲數據的數據庫容器不需要安裝文本編輯器。

 

單一容器只運行單一的服務

大部分情況下一個容器只建議運行一個服務,這樣的好處在於:減小耦合度、利於容器複用以及提高容器的橫向可擴展性。如果服務之間是需要聯繫的,就應該把服務放在不現的容器內,然後用container linking來關聯這些容器以達到目的。

 

最小化鏡像層數(layers)

關於鏡像層數(layers)的概念請參考:docker鏡像與容器存儲結構分析http://www.programfish.com/blog/?p=9

把鏡像層數減到最少可能加快容器的啓動速度,但是這裏也要權衡另一個問題:dockerfile的可讀性。你可以把一個dockerfile寫得很複雜以達到構建出最小層數的鏡像,但同時你的dockerfile可讀性也降低了。所以我們要在鏡像層數和dockerfile可讀性之間做出讓步與妥協。

 

對多行參數進行排序(一般按字母順序)

對參數排序可以方便以後修改更新這些參數以及確保不會重複重複輸入了某些參數。例如官方的一個例子是:

RUN apt-get update && apt-get install -y \

bzr \

cvs \

git \

mercurial \

Subversion

把要安裝的程序包名按字母排序可以方便管理。

 

構建的時候使用cache

Docker build期間docker會按你提供的dockerfile文件裏面的指令按順序逐條執行。Docker在首先檢查每一條指令的時候會去cache裏搜查是否有執行過這條指令並且可以複用的鏡像,如果沒有再去構造一個新的鏡像。這是默認的情況,如果你指定不要這個過程可以在docker build裏用如下參數:

–no-cache=true

Docker查找cache的過程:

首先在cache裏從base image(詳見:docker鏡像與容器存儲結構分析http://www.programfish.com/blog/?p=9)起,docker會比較dockerfile裏的下一條指令與這個base image的每一個子鏡像的構建指令是否匹配,如果匹配則命中,否則cache標爲無效。

對於一般指令這樣簡單比較就足夠了,但是有些精確的指令要求更詳細精確的比較或者說明。 (add和copy指令見官方文檔https://docs.docker.com/articles/dockerfile_best-practices/) 一旦cache在dockerifle裏某一條指令檢查時被標爲無效,執行這個dockerfile以後的指令就不再使用cache。

 

Dockerfile主要指令簡介:

 

FROM   

dockerfile裏的第一條指令,後面跟有效的鏡像名(如果該鏡像你的本地倉庫沒有則會從遠程倉庫Pull取)。後面的指令在些鏡像中執行。

FROM <image>:<tag>

 

MAINTAINER

MAINTAINER <name> 作者信息

 

RUN    

後跟要執行的linux命令,每一條RUN指令(可能會有多條linux命令)會在當前容器最上面的可讀寫層執行並且提交成一個新的鏡像層,接下來的指令會在這個新的鏡像層裏執行。

RUN <command> (the command is run in a shell – /bin/sh -c – shell form)

RUN ["executable", "param1", "param2"] (exec form)

注意下面的情況:  

不要在一條RUN指令裏單一使用apt-get update命令,這樣可能會導致以後的apt-get install 安裝出錯。

避免使用RUN apt-get upgrade 或者dist-upgrade,這樣有些重要的軟件包可能更新失敗,如果你確實想要更新某個包A,使用apt-get install install  -y A 。這樣會自動更新這個軟件包。

更多請參考官方文檔。

 

CMD

CMD指令指定你製作出來的鏡像在啓動成容器時運行命令的默認的參數。

CMD有三種寫法:

CMD ["executable","param1","param2"] (exec form, this is the preferred form)

CMD ["param1","param2"] (as default parameters to ENTRYPOINT)

CMD command param1 param2 (shell form)

第一種是可執行文件加參數,第二種是作爲ENTRYPOINT的參數,第三種是作爲”/bin/sh -c”的參數。

這裏CMD與ENTRYPOINT的區別強烈推薦你去看 論docker CMD與ENTRYPOINT的大區別 http://www.cnblogs.com/programfish/p/4101884.html 這篇文章。看完你就懂了。

 

ENTRYPOINT

ENTRYPOINT字面意思指定容器的進入點。可以把你的容器製作成類似可執行文件的用法。這個指令會覆蓋它前面的CMD指令,而多個ENTRYPOINT指令只有最後一個生效(後面覆蓋前面)。同時你也可以在在啓動container 的時候指定–entrypoint參數來覆蓋dockerfile裏的ENTRYPOINT。詳見官方文檔。

例如我用了這樣的指令製作鏡像名叫echotest:

ENTRYPOINT ["/bin/echo"]

然後之後這樣運行:

docker  run  -it  echotest  “this is a echo”

實際上是平時這樣的命令:

docker  run  -it  echotest  /bin/echo  “this is a echo”

這樣你應該明白了吧。 這樣一個容器的行爲就很類似一個可執行文件了。 這裏CMD與ENTRYPOINT的區別強烈推薦你去看 論docker CMD與ENTRYPOINT的大區別 http://www.cnblogs.com/programfish/p/4101884.html 這篇文章。看完你就懂了。
EXPOSE

EXPOSE指定容器對外暴露的端口號。

 

ENV

指定環境變量的值,例如你要確保CMD[“nginx”]能成功啓動,你應該用ENV PATH /usr/local/nginx/bin:$PATH設定環境變量。另外你可以設定另外一些變量用於RUN命令裏以便於dockerfile文件的維護:

ENV PG_MAJOR 9.3

ENV PG_VERSION 9.3.4

RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …

ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

這樣多次出現版本號就可以通過一個變量來管理方便維護。

 

VOLUME   

VOLUME ["path"] 創建指定的掛載點。

 

WORKDIR   

進入指定目錄工作。

其它指令詳情見官方文檔:https://docs.docker.com/reference/builder/

 

這裏引用官方的一個dockerfile例子:

# Nginx

#

# VERSION               0.0.1

FROM      ubuntu

MAINTAINER  Victor  Vieux  <[email protected]>

RUN  apt-get  update  &&  apt-get install -y  inotify-tools  nginx  apache2  openssh-server

# Firefox over VNC

#

# VERSION               0.3

FROM  ubuntu

# Install  vnc,  xvfb  in  order  to  create  a  ‘fake’  display  and  firefox

RUN  apt-get  update  &&  apt-get  install  -y  x11vnc  xvfb  firefox

RUN  mkdir  ~/.vnc

# Setup  a  password

RUN  x11vnc  -storepasswd  1234  ~/.vnc/passwd

# Autostart  firefox  (might  not  be  the  best  way,  but  it  does  the  trick)

RUN  bash  -c  ‘echo  “firefox”  >>  /.bashrc ‘

EXPOSE  5900

CMD    ["x11vnc",  "-forever" , "-usepw",  "-create" ]

# Multiple  images  example

#

#VERSION               0.1

FROM  ubuntu

RUN  echo  foo  >  bar

# Will  output  something  like ===> 907ad6c2736f

FROM ubuntu

RUN  echo  moo > oink

# Will  output  something  like ===> 695d7793cbe4

# You᾿ll  now  have  two  images, 907ad6c2736f with /bar, and 695d7793cbe4 with

# /oink.

 

#號爲註釋符,這裏一個dockerfile構建4個鏡像。 

寫好Dockerfile文件後就可以在該目錄下運行docker build . 命令了(可以用 -t 參數指定tag)。


 歡迎訪問本人網站:http://www.programfish.com 

LinuxCoder社區: http://linuxcoder.org

注意:轉載請註明 “作者:廣州Linux愛好者+雲計算 刁金明”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章