Dockerfile詳解(一)

 

Dockerfile 用於自動化構建一個docker鏡像。Dockerfile裏有 CMD 與 ENTRYPOINT 兩個功能咋看起來很類似的指令,開始的時候以爲兩個互用沒什麼所謂,但其實並不是如此:linux

CMD指令:docker

The main purpose of a CMD is to provide defaults for an executing container.shell

CMD在容器運行的時候提供一些命令及參數,用法以下:ubuntu

  1. CMD ["executable","param1","param2"] (exec form, this is the preferred form) 
  2. CMD ["param1","param2"] (as default parameters to ENTRYPOINT) 
  3. CMD command param1 param2 (shell form) 
  • 第一種用法:運行一個可執行的文件並提供參數。
  • 第二種用法:爲ENTRYPOINT指定參數。
  • 第三種用法(shell form):是以」/bin/sh -c」的方法執行的命令。

如你指定:bash

  1. CMD [「/bin/echo」, 「this is a echo test 」] 

build後運行(假設鏡像名爲ec):ide

  1. docker run ec 

就會輸出: this is a echo testoop

是否是感受很像開機啓動項,你能夠暫時這樣理解。ui

注意點:this

docker run命令若是指定了參數會把CMD裏的參數覆蓋: (這裏說明一下,如:docker run -it ubuntu /bin/bash 命令的參數是指/bin/bash 而非 -it ,-it只是docker 的參數,而不是容器的參數,如下所說參數均如此。)spa

一樣是上面的ec鏡像啓動:

docker run ec /bin/bash

不會輸出:this is a echo test,由於CMD命令被」/bin/bash」覆蓋了。

ENTRYPOINT  

字面意思是進入點,而它的功能也恰如其意。

An ENTRYPOINT allows you to configure a container that will run as an executable.它可讓你的容器功能表現得像一個可執行程序同樣。

容器功能表現得像一個可執行程序同樣,這是什麼意思呢?

直接給個例子好說話:

例子一:

使用下面的ENTRYPOINT構造鏡像:

  1. ENTRYPOINT ["/bin/echo"] 

那麼docker build出來的鏡像之後的容器功能就像一個/bin/echo程序:

好比我build出來的鏡像名稱叫imageecho,那麼我能夠這樣用它:

  1. docker run -it imageecho 「this is a test」 

這裏就會輸出」this is a test」這串字符,而這個imageecho鏡像對應的容器表現出來的功能就像一個echo程序同樣。 你添加的參數「this is a test」會添加到ENTRYPOINT後面,就成了這樣 /bin/echo 「this is a test」 。如今你應該明白進入點的意思了吧。

例子二:

ENTRYPOINT ["/bin/cat"]

構造出來的鏡像你能夠這樣運行(假設名爲st):

  1. docker run -it st /etc/fstab 

這樣至關: /bin/cat /etc/fstab 這個命令的做用。運行以後就輸出/etc/fstab裏的內容。

ENTRYPOINT有兩種寫法:

寫法一:

  1. ENTRYPOINT ["executable", "param1", "param2"] (the preferred exec form) 

寫法二:

  1. ENTRYPOINT command param1 param2 (shell form) 

你也能夠在docker run 命令時使用–entrypoint指定(可是隻能用寫法一)。

下面是我把ENTRYPOINT設爲[「/bin/sh -c」]時候運行的狀況:

  1. linux-oj9e:/home/lfly/project/docker # docker run -it t2 /bin/bash 
  2. root@4c8549e7ce3e:/# ps 
  3. PID TTY TIME CMD 
  4. 1 ? 00:00:00  sh 
  5. 9 ? 00:00:00  bash 
  6. 19 ? 00:00:00  ps 

能夠看到PID爲1的進程運行的是sh,而bash只是sh的一個子進程,/bin/bash只是做爲 /bin/sh -c後面的參數。

CMD能夠爲ENTRYPOINT提供參數,ENTRYPOINT自己也能夠包含參數,可是你能夠把那些可能須要變更的參數寫到CMD裏而把那些不須要變更的參數寫到ENTRYPOINT裏面例如:

  1. FROM ubuntu:14.10  
  2. ENTRYPOINT ["top", "-b"]   
  3. CMD ["-c"]  

把可能須要變更的參數寫到CMD裏面。而後你能夠在docker run裏指定參數,這樣CMD裏的參數(這裏是-c)就會被覆蓋掉而ENTRYPOINT裏的不被覆蓋。

注意點1:

ENTRYPOINT有兩種寫法,第二種(shell form)會屏蔽掉docker run時後面加的命令和CMD裏的參數。

注意點2:

網上有資料說ENTRYPOINT的默認值是[」/bin/sh -c」],可是筆者在試驗的時候獲得的結果並非這樣的。

筆者使用ENTRYPOINT [「/bin/sh -c」] 指令構造一個以/bin/sh -c爲進入點的鏡像,命名爲sh,而後我能夠這樣運行:

  1. docker run -it sh 「while(ture ) do echo loop; done」 

運行結果就是無限輸出loop。但若是直接運行一個ubuntu:14.10鏡像,狀況不是這樣的:

  1. docker run -it ubuntu:14.10 「while(ture ) do echo loop; done」 

獲得這樣的錯誤:

  1. linux-oj9e:/home/lfly # docker run -it ubuntu:14.10 「while(true) do echo this; done」 2014/11/16 18:07:53 Error response from daemon: Cannot start container 4bfe9c6faeec3ed465788a201a2f386cb1af35aba197dbc78b87c0d5dda1f88e: exec: 「while(true) do echo this; done」: executable file not found in $PATH 

能夠猜測默認狀況下ENTRYPOINT並非[「/bin/sh -c」]。

並且直接運行ubuntu:14.10列出程序也能夠看到PID爲1的程序並非sh。因此更否認了網友的說法,ENTRYPOINT並不默認爲[「/bin/sh -c」] 。

原文出自:http://www.programfish.com/blog/?p=151

相關文章
相關標籤/搜索