Dockerfile中RUN CMD以及ENTRYPOINT的區別
Dockerfile中的RUN,CMD,ENTRTPOINT三個指令均可以用來指明容器中所執行的指令,但這三者存在的細微的區別。
簡單來說:
RUN
RUN指令一般用於在容器內安裝軟體包或者是執行其他的命令,如
RUN yum install -y telnet
RUN touch web.xml
CMD
CMD指令主要用來指明生成的Docker映象在啟動時的命令及引數,這個指令可以被docker run後面的命令所取代,比如下面這個Dockerfile檔案
FROM busybox
CMD echo "hello world"
CMD指明瞭Docker映象在執行時的輸出一個"hello world"
[root@bochs Docker]# docker build -t test . Sending build context to Docker daemon 2.048kB Step 1/2 : FROM busybox ---> 83aa35aa1c79 Step 2/2 : CMD echo "hello world" ---> Running in a1a4d74137d2 Removing intermediate container a1a4d74137d2 ---> 651b45b58fe9 Successfully built 651b45b58fe9 Successfully tagged test:latest [root@bochs Docker]# docker run -it test hello world
但是如果在docker run後新增其他指令。那麼CMD將直接被替換
[root@bochs Docker]# docker run -it test ls
bin dev etc home proc root sys tmp usr var
ENTRYPOINT
ENTRYPOINT與CMD類似,區別在於ENTRYPOINT一定會被執行。如果一個Dockerfile中同時存在ENTRYPOINT和
CMD,CMD中的引數會被當做額外引數傳給ENTRYPOINT。
[root@bochs Docker]# cat Dockerfile FROM busybox ENTRYPOINT ["/bin/echo","hello"] CMD ["world"]
通過docker run 來執行,CMD變成了ENTRYPOINT的引數:
[root@bochs Docker]# docker run -it test2
hello world
但是如果指明docker run 的引數china,那麼輸出就會變為:
[root@bochs Docker]# docker run -it test2 china
hello china
原本CMD中帶的引數world被docker run中的china所替換,但ENTRYPOINT自帶的hello依然正常輸出
Shell與Exec格式
CMD,RUN,ENTRYPOINT可以用兩種格式來傳遞命令和引數,Shell一般表示為指令+命令,如:
RUN yum install -y telnet
CMD echo "hello world"
第一個大寫的單詞是Dockerfile的指令。後面跟的就是命令,可以拿到shell中單獨執行
Exec格式可以表示為:指令+["命令","命令引數1","命令引數2",...],比如:
RUN ["yum","install","telnet"]
ENTRYPOINT ["/bin/bash","-c","echo hello world"]
對於這兩種格式來說,CMD和ENTRYPOINT最好使用Exec格式,命令和引數分開,層次性較強,而RUN則都可以。
注意:ENTRYPOINT的Shell格式和Exec格式差異很大
比如下面這個Shell格式的ENTRYPOINT
FROM busybox
ENTRYPOINT echo "hello"
CMD "world"
在執行所生成的容器時,僅會輸出hello,而CMD帶的"world"會被忽略。同樣的docker run帶的引數也同樣會被忽略
[root@bochs Docker]# docker run -it test
hello
[root@bochs Docker]# docker run -it test china
hello