apt-get update 和 apt-get install 寫在同一個 RUN 指令的解讀

Codcodog發表於2019-02-21

場景

看到很多 Dockerfile 都是把 apt-get updateapt-get install 寫在同一個 RUN 指令中的

RUN apt-get update && apt-get install -y \
        package-bar \
        package-baz \
        package-foo

而不是

RUN apt-get update
RUN apt-get install -y \
        package-bar \
        package-baz \
        package-foo

只知道這樣寫在同一個 RUN 中會減少 layer 層,縮減構建映象的大小.

但看到有一些文章提到,只有寫在同一個 RUN 中才會對後面的 apt-get install 生效,卻沒有細說原因.

因此產生了一個疑惑,分開寫也應該會對後面的 apt-get install 生效才對啊,因為映象的構建是一層一層的,後面的層會基於前面的層.
也就是說,RUN apt-get update 會單獨構建一層,並且會對後面 RUN apt-get install 的層產生作用才對.

分析

假設有一個這樣的 Dockerfile

FROM ubuntu:14.04
RUN apt-get update
RUN apt-get install -y curl

構建映象之後,所有的層都會在 Docker 的快取中.
假設後來修改 apt-get install 新增額外的包

 FROM ubuntu:14.04
 RUN apt-get update
 RUN apt-get install -y curl nginx

Docker 將初始和修改的指令視為相同,並會重用之前構建的快取.
因此,不會執行 apt-get update,因為構建直接使用之前的快取版本.
由於 apt-get update 沒有執行,所以構建安裝的 curlnginx 包很可能是過時的版本.

所以,把 apt-get updateapt-get install 寫在同一個 RUN 中以獲取最新版本的包,而且還減少了 layer 層.

參考
Best practices for writing Dockerfiles

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章