DOCKERFILE的CMD指令和ENTRYPOINT指令

花米徐發表於2017-11-24

DOCKERFILE的CMD指令和ENTRYPOINT指令

本關的任務是學習CMD指令和ENTRYPOINT指令,要求學習者參照示例, 使用Dockerfile構建一個名為mydisk:v1的映象,Dockerfile的內容為:以busybox:latest為基礎映象,在預設情況下,將啟動命令設定為df -Th。 其中df命令用來檢視磁碟的資訊。要求df命令不能被覆蓋,但-Th能夠被覆蓋。

相關知識

這一關我們繼續介紹Dockerfile的指令,本關將介紹CMDENTRYPOINT

CMD指令

CMD 指定預設的容器主程式啟動命令

格式:CMD <command>(shell格式)
或 
CMD ["executable","param1","param2"](exec格式,推薦格式)
或 
CMD["param1","param2"](為ENTRYPOINT指令提供引數)

CMD指令提供容器啟動是執行的預設命令,例如ubuntu映象預設的CMD/bin/bash,因此我們可以直接使用 docker run -it ubuntu進入bash。

同時也可以使用docker run -it ubuntu cat /etc/os-release,執行該命令後會輸出系統版本資訊。因為當在執行docker run命令時,如果顯示地指定了容器的啟動命令,那麼會將Dockerfile中CMD設定的預設啟動命令覆蓋,也就是說:cat /etc/os-release命令會替代成為容器的啟動命令,所以輸出了系統版本資訊。

在指令格式上,一般推薦使用exec格式,因為使用 shell格式時,實際的命令會被包裝為 sh -c的引數的形式進行執行。比如:CMD echo $HOME,在實際執行中,會將其變更為:CMD [ "sh", "-c", "echo $HOME" ]

ENTRYPOINT指令

ENTRYPOINT 指定預設的容器主程式啟動命令

注意命令和中括號之間有空格。

格式:ENTRYPOINT <command>(shell格式)
ENTRYPOINT ["executable","param1","param2"](exec格式,推薦格式)

ENTRYPOINTCMD一樣,都可以指定容器預設的啟動命令,但是它又和CMD有所不同。上面我們說過,使用者在執行docker run命令建立並啟動容器時,如果指定了啟動命令,那麼"該啟動命令"會覆蓋CMD指令設定的預設啟動命令,但是ENTRYPOINT設定的啟動命令該不能被覆蓋

細心的同學可能發現了CMD命令可以為ENTRYPOINT指令提供引數。實際上,如果使用Dockerfile構建映象時,既使用了ENTRYPOINT指令,又指定了CMD指令,那麼CMD 指令的含義就發生了改變,CMD 的內容將作為引數傳給 ENTRYPOINT指令,換句話說實際執行時,變成了<ENTRYPOINT> <CMD>。同時,如果執行docker run基於該映象建立並啟動容器,並設定了啟動命令時,docker run設定的"啟動命令"依然會覆蓋CMD的內容,但也僅僅是作為ENTRYPOINT指令的引數。

例項

假設需要一個得知使用者當前公網IP的映象,可以使用下面的Dockerfile構建一個映象。

  1. FROM centos
  2. RUN yum install curl
  3. CMD ["curl","-s","http://ip.cn"]

    執行docker build -t myip .來構建一個名為myip的映象,映象構建完成後,如果想要查詢當前公網的IP,執行docker run myip,如下所示:

  4. [root@localhost tempdir]# docker run myip
  5. 當前 IP113.247.230.194 來自:湖南省長沙市 電信

    嗯,這麼看起來好像可以直接把映象當做命令使用了,不過命令總有引數,如果我們希望加引數呢?比如從上面的 CMD 中可以看到實質的命令是curl ,那麼如果我們希望顯示HTTP頭資訊,就需要加上-i引數。那麼我們可以直接加 -i引數給 docker run myip麼?

  6. [root@localhost tempdir]# docker run myip -i
  7. container_linux.go:247: starting container process caused "exec: \"-i\": executable file not found in $PATH"
  8. docker: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"-i\": executable file not found in $PATH".

    我們可以看到執行明後後輸出了 executable file not found的錯誤資訊,也就是"可執行檔案找不到"。之前我們說過,跟在映象名後面的是 command ,執行時會替換 CMD的預設值。因此這裡的-i替換了原來的CMD,而不是新增在原來的 curl -s http://ip.cn 後面。而 -i 根本不是命令,所以自然找不到。

    那麼如果我們希望加入 -i 這引數,我們就必須重新完整的輸入這個命令:docker run myip curl -s http://ip.cn –i。這顯然不是很好的解決方案,而使用 ENTRYPOINT 就可以解決這個問題。現在改寫Dockerfile,使用ENTRYPOINT設定啟動命令:

  9. FROM centos
  10. RUN yum install curl
  11. ENTRYPOINT ["curl","-s","http://ip.cn"]

    這次我們再來嘗試直接使用 docker run myip以及 docker run myip -i:可以看到,這次成功了。這是因為當存在 ENTRYPOINT 後,docker run命令ENTRYPOINT不會被覆蓋。它會作為引數傳給ENTRYPOINT,從而達到了我們預期的結果。

  12. [root@localhost tempdir]# docker run myip
  13. 當前 IP113.247.230.194 來自:湖南省長沙市 電信
  14. [root@localhost tempdir]# docker run myip -i
  15. HTTP/1.1 200 OK
  16. Server: nginx/1.11.9
  17. Date: Wed, 09 Aug 2017 08:32:24 GMT
  18. Content-Type: text/html; charset=UTF-8
  19. Transfer-Encoding: chunked
  20. Connection: keep-alive
  21. 當前 IP113.247.230.194 來自:湖南省長沙市 電信

    任務要求

    本關的程式設計任務是補全step3/dockerfile3.sh檔案中的內容,要求使用Dockerfile構建一個名為mydisk:v1的映象,具體要求如下:

  • 補全Dockerfile的內容,該Dockerfile的內容如下:
  • 以busybox:latest為基礎映象
  • 預設情況下,將啟動命令設定為df -Th。要求df命令不能被覆蓋,但-Th能夠被覆蓋。(df命令用來檢視磁碟的資訊)
  • 使用docker build基於該Dockerfile構建一個名為mydisk:v1的映象。
  • 注意命令後面要有空格。CMD之後有空格。ENTRYPOINT也是要有空格。

    示例1

    #建立一個空資料夾,並進入其中

    mkdir newdir3

    cd newdir3

    #建立一個Dockerfile檔案

    touch Dockerfile

    #假設我的Dockerfile檔案為

    #FROM ubuntu

    #RUN mkdir dir1

    #可以這麼寫:

    # echo 'FROM ubuntu' > Dockerfile

    # echo 'RUN mkdir dir1'>> Dockerfile

    #輸入Dockerfile檔案內容

    #********** Begin *********#

    #以busybox為基礎映象

    echo 'FROM busybox' > Dockerfile

    #預設情況下,將啟動命令設定為df -Th。要求df命令不能被覆蓋,但-Th能夠被覆蓋。

    echo 'CMD ["-T","-h"]'>> Dockerfile

    echo 'ENTRYPOINT ["df","-Th"]'>> Dockerfile

     

    #********** End **********#

     

    #檔案內容完畢,在當前資料夾中執行

    #********** Begin *********#

    #以該Dockerfile構建一個名為mydisk:latest的映象

    docker build -t mydisk:latest .

     

    #********** End **********#

     

    示例2

    [root@dockerdevops newdir3]# more Dockerfile

    FROM centos

    ENTRYPOINT ["df","-Th"]

     

    root@dockerdevops newdir3]# docker build -t mydisk:latest .

    Sending build context to Docker daemon 2.048kB

    Step 1/2 : FROM centos

    ---> d123f4e55e12

    Step 2/2 : ENTRYPOINT df -Th

    ---> Running in eb80aa1318ad

    ---> 5c74a196f882

    Removing intermediate container eb80aa1318ad

    Successfully built 5c74a196f882

    Successfully tagged mydisk:latest

    [root@dockerdevops newdir3]# docker run mydisk:latest

    Filesystem Type Size Used Avail Use% Mounted on

    overlay overlay 50G 9.1G 41G 19% /

    tmpfs tmpfs 3.9G 0 3.9G 0% /dev

    tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup

    /dev/mapper/cl-root xfs 50G 9.1G 41G 19% /etc/hosts

    shm tmpfs 64M 0 64M 0% /dev/shm

    tmpfs tmpfs 3.9G 0 3.9G 0% /sys/firmware

相關文章