【Docker】Dockerfile 最佳實踐-RUN
參考教程:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
環境
- virtual box 6.1
- centos 7.8
- docker 19.03
RUN
Split long or complex RUN
statements on multiple lines separated with backslashes to make your Dockerfile
more readable, understandable, and maintainable.
在多行上用反斜槓分隔長或複雜的 RUN
語句,以使您的 Dockerfile
apt-get
Probably the most common use-case for RUN
is an application of apt-get
. Because it installs packages, the RUN apt-get
command has several gotchas to look out for.
RUN
的最常見用例可能是 apt-get
的應用程式。因為它安裝了軟體包,所以 RUN apt-get
命令需要注意一些陷阱。
Avoid RUN apt-get upgrade
and dist-upgrade
, as many of the “essential” packages from the parent images cannot upgrade inside an foo
, that needs to be updated, use apt-get install -y foo
to update automatically.
避免使用 RUN apt-get upgrade
和 dist-upgrade
,因為來自父映像的許多“基本”軟體包都無法在非特權容器
foo
需要更新,請使用 apt-get install -y foo
自動更新。
Always combine RUN apt-get update
with apt-get install
in the same RUN
statement. For example:
始終在同一 RUN
語句中將 RUN apt-get update
和 apt-get install
結合使用。例如:
RUN apt-get update && apt-get install -y \
package-bar \
package-baz \
package-foo \
&& rm -rf /var/lib/apt/lists/*
Using apt-get update
alone in a RUN
statement causes caching issues and subsequent apt-get install
instructions fail. For example, say you have a Dockerfile:
在 RUN
語句中單獨使用 apt-get update
會導致快取問題,隨後的 apt-get install
指令也會失敗。例如,假設您有一個 Dockerfile:
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y curl
After building the image, all layers are in the Docker cache. Suppose you later modify apt-get install
by adding extra package:
構建映象後,所有層都在 Docker 快取中。假設您以後通過新增額外的軟體包來修改 apt-get install
:
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y curl nginx
Docker sees the initial and modified instructions as identical and reuses the cache from previous steps. As a result the apt-get update
is not executed because the build uses the cached version. Because the apt-get update
is not run, your build can potentially get an outdated version of the curl
and nginx
packages.
Docker 將初始指令和修改後的指令視為相同,並重復使用先前步驟中的快取。結果,由於構建使用了快取的版本,因此未執行 apt-get update
。因為沒有執行 apt-get update
,所以您的構建可能會獲得 curl
和 nginx
軟體包的過時版本。
Using RUN apt-get update && apt-get install -y
ensures your Dockerfile installs the latest package versions with no further coding or manual intervention. This technique is known as “cache busting”. You can also achieve cache-busting by specifying a package version. This is known as version pinning, for example:
使用 RUN apt-get update && apt-get install -y
確保您的 Dockerfile 安裝最新的軟體包版本,而無需進一步的編碼或手動干預。這種技術稱為“快取清除”。您還可以通過指定軟體包版本來實現快取清除。這稱為版本固定,例如:
RUN apt-get update && apt-get install -y \
package-bar \
package-baz \
package-foo=1.3.*
Version pinning forces the build to retrieve a particular version regardless of what’s in the cache. This technique can also reduce failures due to unanticipated changes in required packages.
版本固定會強制構建物檢索特定版本,而不管快取中的內容是什麼。該技術還可以減少由於所需包裝中的意外更改而導致的故障。
Below is a well-formed RUN
instruction that demonstrates all the apt-get
recommendations.
下面是格式正確的 RUN
指令,演示了所有 apt-get
建議。
RUN apt-get update && apt-get install -y \
aufs-tools \
automake \
build-essential \
curl \
dpkg-sig \
libcap-dev \
libsqlite3-dev \
mercurial \
reprepro \
ruby1.9.1 \
ruby1.9.1-dev \
s3cmd=1.1.* \
&& rm -rf /var/lib/apt/lists/*
The s3cmd
argument specifies a version 1.1.*
. If the image previously used an older version, specifying the new one causes a cache bust of apt-get update
and ensures the installation of the new version. Listing packages on each line can also prevent mistakes in package duplication.
s3cmd
引數指定版本 1.1。*
。如果映象先前使用的是舊版本,則指定新版本會導致 apt-get update
快取崩潰,並確保安裝新版本。在每一行列出軟體包還可以防止軟體包重複中的錯誤。
In addition, when you clean up the apt cache by removing /var/lib/apt/lists
it reduces the image size, since the apt cache is not stored in a layer. Since the RUN
statement starts with apt-get update
, the package cache is always refreshed prior to apt-get install
.
另外,當您通過刪除 /var/lib/apt/lists
清理 apt 快取時,由於 apt 快取沒有儲存在圖層中,因此會減小映像大小。由於 RUN 語句以 apt-get update
開頭,因此軟體包快取總是在 apt-get install
之前重新整理。
Official Debian and Ubuntu images automatically run
apt-get clean
, so explicit invocation is not required.
官方 Debian 和 Ubuntu 映象自動執行
apt-get clean
,因此不需要顯式呼叫。
Using pipes
Some RUN
commands depend on the ability to pipe the output of one command into another, using the pipe character (|
), as in the following example:
一些 RUN
命令取決於使用管道字元(|
)將一個命令的輸出管道到另一個命令的能力,如以下示例所示:
RUN wget -O - https://some.site | wc -l > /number
Docker executes these commands using the /bin/sh -c
interpreter, which only evaluates the exit code of the last operation in the pipe to determine success. In the example above this build step succeeds and produces a new image so long as the wc -l
command succeeds, even if the wget
command fails.
Docker 使用 /bin/sh -c
直譯器執行這些 命令,該直譯器僅評估管道中最後一個操作的退出程式碼來確定成功。在上面的示例中,即使 wget
命令失敗,只要wc -l
命令成功,該構建步驟就會成功並生成一個新映象。
If you want the command to fail due to an error at any stage in the pipe, prepend set -o pipefail &&
to ensure that an unexpected error prevents the build from inadvertently succeeding. For example:
如果您希望命令由於管道中任何階段的錯誤而失敗,請新增 set -o pipefail &&
字首,以確保意外錯誤可以防止構建意外進行。例如:
RUN set -o pipefail && wget -O - https://some.site | wc -l > /number
Not all shells support the
-o pipefail
option.並非所有的 shell 都支援
-o pipefail
選項。In cases such as the
dash
shell on Debian-based images, consider using the exec form ofRUN
to explicitly choose a shell that does support thepipefail
option. For example:在諸如基於 Debian 的映象上的
dash
外殼的情況下,請考慮使用 RUN 的 exec 形式來明確選擇一個支援pipefail
選項的外殼。例如:RUN ["/bin/bash", "-c", "set -o pipefail && wget -O - https://some.site | wc -l > /number"]
總結
介紹了 Dockerfile 的 RUN 指令的最佳實踐。