(九)RUN vs CMD vs ENTRYPOINT
(1)命令簡介
- RUN 執行命令并創建新的鏡像層,RUN 經常用于安裝軟體包,
- CMD 設定容器啟動后默認執行的命令及其引數,但 CMD 能夠被
docker run后面跟的命令列引數替換, - ENTRYPOINT 配置容器啟動時運行的命令,
(2)Shell 和 Exec 格式
? 我們可用兩種方式指定 RUN、CMD 和 ENTRYPOINT 要運行的命令:Shell 格式和 Exec 格式,二者在使用上有細微的區別,
Shell 格式
<instruction> <command>
例如:
RUN apt-get install python3
CMD echo "Hello world"
ENTRYPOINT echo "Hello world"
當指令執行時,shell 格式底層會呼叫 /bin/sh -c
例如下面的 Dockerfile 片段:
ENV name Cloud Man
ENTRYPOINT echo "Hello, $name"
執行 docker run 將輸出: 注意環境變數
name 已經被值 Cloud Man 替換,
Hello, Cloud Man
Exec 格式 :
Exec 格式
<instruction> ["executable", "param1", "param2", ...]
例如:
RUN ["apt-get", "install", "python3"]
CMD ["/bin/echo", "Hello world"]
ENTRYPOINT ["/bin/echo", "Hello world"]
當指令執行時,會直接呼叫
ENV name Cloud Man
ENTRYPOINT ["/bin/echo", "Hello, $name"]
運行容器將輸出:
Hello, $name
注意環境變數“name”沒有被替換, 如果希望使用環境變數,照如下修改
ENV name Cloud Man
ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]
運行容器將輸出:
Hello, Cloud Man
CMD 和 ENTRYPOINT 推薦使用 Exec 格式,因為指令可讀性更強,更容易理解,RUN 則兩種格式都可以,
(3)RUN命令
RUN 指令通常用于安裝應用和軟體包,
RUN 在當前鏡像的頂部執行命令,并通過創建新的鏡像層,Dockerfile 中常常包含多個 RUN 指令,
RUN 有兩種格式:
- Shell 格式:RUN
- Exec 格式:RUN ["executable", "param1", "param2"]
下面是使用 RUN 安裝多個包的例子:
RUN apt-get update && apt-get install -y \
bzr \
cvs \
git \
mercurial \
subversion
注意:apt-get update 和 apt-get install 被放在一個 RUN 指令中執行,這樣能夠保證每次安裝的是最新的包,如果 apt-get install 在單獨的 RUN 中執行,則會使用 apt-get update 創建的鏡像層,而這一層可能是很久以前快取的,
(4)CMD
CMD 指令允許用戶指定容器的默認執行的命令,此命令會在容器啟動且 docker run 沒有指定其他命令時運行,
- 如果 docker run 指定了其他命令,CMD 指定的默認命令將被忽略,
- 如果 Dockerfile 中有多個 CMD 指令,只有最后一個 CMD 有效,
CMD 有三種格式:
1. Exec 格式:CMD ["executable","param1","param2"]
這是 CMD 的推薦格式,
2. CMD ["param1","param2"] 為 ENTRYPOINT 提供額外的引數,此時 ENTRYPOINT 必須使用 Exec 格式,
3. Shell 格式:CMD command param1 param2
? Exec 和 Shell 格式前面已經介紹過了, 第二種格式 CMD ["param1","param2"] 要與 Exec 格式 的 ENTRYPOINT 指令配合使用,其用途是為 ENTRYPOINT 設定默認的引數,
CMD 作業情況,Dockerfile 片段如下:
CMD echo "Hello world"
運行容器 docker run -it [image] 將輸出:
Hello world
但當后面加上一個命令,比如 docker run -it [image] /bin/bash,CMD 會被忽略掉,命令 bash 將被執行:
root@10a32dc7d3d3:/#
(5)ENTRYPOINT
ENTRYPOINT 指令可讓容器以應用程式或者服務的形式運行,
ENTRYPOINT 看上去與 CMD 很像,它們都可以指定要執行的命令及其引數,不同的地方在于 ENTRYPOINT 不會被忽略,一定會被執行,即使運行 docker run 時指定了其他命令,
ENTRYPOINT 有兩種格式:
1.Exec 格式:ENTRYPOINT ["executable", "param1", "param2"] 這是 ENTRYPOINT 的推薦格式,
2.Shell 格式:ENTRYPOINT command param1 param2
在為 ENTRYPOINT 選擇格式時必須小心,因為這兩種格式的效果差別很大,
①Exec 格式
ENTRYPOINT 的 Exec 格式用于設定要執行的命令及其引數,同時可通過 CMD 提供額外的引數,
ENTRYPOINT 中的引數始侄訓被使用,而 CMD 的額外引數可以在容器啟動時動態替換掉,
Dockerfile 片段:
ENTRYPOINT ["/bin/echo", "Hello"]
CMD ["world"]
當容器通過 docker run -it [image] 啟動時,輸出為:
Hello world
而如果通過 docker run -it [image] CloudMan 啟動,則輸出為:
Hello CloudMan
②Shell 格式
ENTRYPOINT 的 Shell 格式會忽略任何 CMD 或 docker run 提供的引數,
(6)最優方式
-
使用 RUN 指令安裝應用和軟體包,構建鏡像,
-
如果 Docker 鏡像的用途是運行應用程式或服務,比如運行一個 MySQL,應該優先使用 Exec 格式的 ENTRYPOINT 指令,CMD 可為 ENTRYPOINT 提供額外的默認引數,同時可利用 docker run 命令列替換默認引數,
-
如果想為容器設定默認的啟動命令,可使用 CMD 指令,用戶可在 docker run 命令列中替換此默認命令,
到這里,我們已經具備撰寫 Dockerfile 的能力了,如果大家還覺得沒把握,推薦一個快速掌握 Dockerfile 的方法:去 Docker Hub 上參考那些官方鏡像的 Dockerfile,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/202438.html
標籤:其他
