場景
看到很多 Dockerfile
都是把 apt-get update
和 apt-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
沒有執行,所以構建安裝的 curl
和 nginx
包很可能是過時的版本.
所以,把 apt-get update
和 apt-get install
寫在同一個 RUN
中以獲取最新版本的包,而且還減少了 layer
層.
參考
Best practices for writing Dockerfiles
本作品採用《CC 協議》,轉載必須註明作者和本文連結