RUN vs CMD vs ENTRYPOINT - 每天5分鐘玩轉 Docker 容器技術(17)
RUN、CMD 和 ENTRYPOINT 這三個 Dockerfile 指令看上去很類似很容易混淆。本節將通過實踐詳細討論它們的區別。
簡單的說
-
RUN 執行命令並建立新的映象層RUN 經常用於安裝軟體包。
-
CMD 設定容器啟動後預設執行的命令及其引數但 CMD 能夠被
docker run
後面跟的命令列引數替換。 -
ENTRYPOINT 配置容器啟動時執行的命令。
下面我們詳細分析。
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 <command> 。
例如下面的 Dockerfile 片段
ENV name Cloud Man
ENTRYPOINT echo "Hello, $name"
執行 docker run <image> 將輸出
Hello, Cloud Man
注意環境變數 name
已經被值 Cloud Man
替換。
下面來看 Exec 格式。
Exec 格式
<instruction> ["executable", "param1", "param2", ...]
例如
RUN ["apt-get", "install", "python3"]
CMD ["/bin/echo", "Hello world"]
ENTRYPOINT ["/bin/echo", "Hello world"]
當指令執行時會直接呼叫 <command>不會被 shell 解析。
例如下面的 Dockerfile 片段
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 則兩種格式都可以。
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 建立的映象層而這一層可能是很久以前快取的。
CMD
CMD 指令允許使用者指定容器的預設執行的命令。
此命令會在容器啟動且 docker run 沒有指定其他命令時執行。
-
如果 docker run 指定了其他命令CMD 指定的預設命令將被忽略。
-
如果 Dockerfile 中有多個 CMD 指令只有最後一個 CMD 有效。
CMD 有三種格式
-
Exec 格式CMD ["executable","param1","param2"]
這是 CMD 的推薦格式。 -
CMD ["param1","param2"] 為 ENTRYPOINT 提供額外的引數此時 ENTRYPOINT 必須使用 Exec 格式。
-
Shell 格式CMD command param1 param2
Exec 和 Shell 格式前面已經介紹過了。
第二種格式 CMD ["param1","param2"] 要與 Exec 格式 的 ENTRYPOINT 指令配合使用其用途是為 ENTRYPOINT 設定預設的引數。我們將在後面討論 ENTRYPOINT 時舉例說明。
下面看看 CMD 是如何工作的。Dockerfile 片段如下
CMD echo "Hello world"
執行容器 docker run -it [image] 將輸出
Hello world
但當後面加上一個命令比如 docker run -it [image] /bin/bashCMD 會被忽略掉命令 bash 將被執行
root@10a32dc7d3d3:/#
ENTRYPOINT
ENTRYPOINT 指令可讓容器以應用程式或者服務的形式執行。
ENTRYPOINT 看上去與 CMD 很像它們都可以指定要執行的命令及其引數。不同的地方在於 ENTRYPOINT 不會被忽略一定會被執行即使執行 docker run 時指定了其他命令。
ENTRYPOINT 有兩種格式
-
Exec 格式ENTRYPOINT ["executable", "param1", "param2"] 這是 ENTRYPOINT 的推薦格式。
-
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 提供的引數。
最佳實踐
-
使用 RUN 指令安裝應用和軟體包構建映象。
-
如果 Docker 映象的用途是執行應用程式或服務比如執行一個 MySQL應該優先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可為 ENTRYPOINT 提供額外的預設引數同時可利用 docker run 命令列替換預設引數。
-
如果想為容器設定預設的啟動命令可使用 CMD 指令。使用者可在 docker run 命令列中替換此預設命令。
到這裡我們已經具備編寫 Dockerfile 的能力了。如果大家還覺得沒把握推薦一個快速掌握 Dockerfile 的方法去 Docker Hub 上參考那些官方映象的 Dockerfile。
好了我們已經學習完如何建立自己的 image下一節討論如何分發 image。
本文轉自CloudMan6 51CTO部落格,原文連結:http://blog.51cto.com/cloudman/1927363
相關文章
- 每天5分鐘玩轉Docker容器技術(二)Docker
- 【Docker】(9)---每天5分鐘玩轉 Docker 容器技術之映象Docker
- Kubernetes Dashboard - 每天5分鐘玩轉 Docker 容器技術(173)Docker
- 回收 PV - 每天5分鐘玩轉 Docker 容器技術(152)Docker
- Network Policy - 每天5分鐘玩轉 Docker 容器技術(171)Docker
- Prometheus Operator - 每天5分鐘玩轉 Docker 容器技術(177)PrometheusDocker
- PV & PVC - 每天5分鐘玩轉 Docker 容器技術(150)Docker
- 外部 Storage Provider - 每天5分鐘玩轉 Docker 容器技術(149)IDEDocker
- Liveness 探測 - 每天5分鐘玩轉 Docker 容器技術(143)Docker
- Helm 架構 - 每天5分鐘玩轉 Docker 容器技術(161)架構Docker
- 再次實踐 MySQL chart - 每天5分鐘玩轉 Docker 容器技術MySqlDocker
- 什麼是 stack?- 每天5分鐘玩轉 Docker 容器技術(111)Docker
- MySQL 使用 PV 和 PVC - 每天5分鐘玩轉 Docker 容器技術(154)MySqlDocker
- 通過 Service 訪問 Pod - 每天5分鐘玩轉 Docker 容器技術(136)Docker
- Kubernetes 叢集日誌管理 - 每天5分鐘玩轉 Docker 容器技術(180)Docker
- ELK 完整部署和使用 - 每天5分鐘玩轉 Docker 容器技術(90)Docker
- 部署 Graylog 日誌系統 - 每天5分鐘玩轉 Docker 容器技術(92)Docker
- 如何用 Graylog 管理日誌? - 每天5分鐘玩轉 Docker 容器技術(93)Docker
- 用 Weave Scope 監控叢集 - 每天5分鐘玩轉 Docker 容器技術(175)Docker
- 在滾動更新中使用 Health Check - 每天5分鐘玩轉 Docker 容器技術(146)Docker
- 萬能資料收集器 Fluentd - 每天5分鐘玩轉 Docker 容器技術(91)Docker
- 用 k8s 管理機密資訊 - 每天5分鐘玩轉 Docker 容器技術(155)K8SDocker
- Dockerfile 中 RUN, CMD, ENTRYPOINT 的區別Docker
- 017、RUN、CMD、ENTRYPOINT (2019-01-08 週二)
- docker筆記15-Dockerfile案例-CMD、ENTRYPOINT案例Docker筆記
- CMD和ENTRYPOINT命令
- Kubernetes vs Docker:瞭解 2021 年的容器Docker
- Vagrant Vs, DockerDocker
- Docker Vs PodmanDocker
- [轉帖]Dockerfile中CMD與ENTRYPOINT命令的區別Docker
- Docker--容器技術Docker
- docker容器技術原理Docker
- 玩轉docker之自定義PHP容器DockerPHP
- Oracle vs PostgreSQL Develop(17) - ARRAYOracleSQLdev
- 探秘Kubernetes:在本地環境中玩轉容器技術
- Docker技術( 容器虛擬化技術 )Docker
- Docker容器技術與Docker介紹Docker
- 容器技術之Docker映象Docker
- .NET - Task.Run vs Task.Factory.StartNew