Dockerfile構建指南-怎樣構建一個適用企業級的鏡像

拋磚引玉nginx

先說結論


  1. 以不變應萬變
  • 一個相對固定的 build 環境
  • 善用 cache
  • 構建 本身的基礎鏡像

2 . 精簡爲美docker

  • 緩存清理
  • multi stage build
  • 使用 .dockerignore 保持 context 乾淨
  • 容器鏡像環境清理

你須要的瞭解的參考資料

爲何要優化鏡像


  • 一個小鏡像有什麼好處: 分發更快,存儲更少,加載更快。
  • 鏡像臃腫帶來了什麼問題: 存儲過多,分發更慢且浪費帶寬更多。

鏡像的構成

Dockerfile構建指南-怎樣構建一個適用企業級的鏡像

  • 俯瞰鏡像: 就是一個刪減版的操做系統。
  • 側看鏡像: 由一層層的 layer 堆疊而成

那麼問題來了


  1. 是否層數少的鏡像, 就是一個好鏡像?
  2. 在企業應用中, 要怎麼去規劃和建設 CI中的鏡像和構建 ?
  3. 帶集羣足夠大, 節點足夠多的時候, 要怎麼快速分發這些鏡像 ?

舉個例子 docker build


  • Dockerfile v1
# v1
FROM nginx:1.15-alpine

RUN echo "hello"

RUN echo "demo best practise"

ENTRYPOINT [ "/bin/sh" ]
  • Dockerfile v2
# v2
FROM nginx:1.15-alpine

RUN echo "hello"

RUN echo "demo best practise 02"

ENTRYPOINT [ "/bin/sh" ]
  • 1st build

全新構建緩存

# docker build -t demo:0.0.1 .                          Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM nginx:1.15-alpine
 ---> 9a2868cac230
Step 2/4 : RUN echo "hello"
 ---> Running in d301b4b3ed55
hello
Removing intermediate container d301b4b3ed55
 ---> 6dd2a7773bbc
Step 3/4 : RUN echo "demo best practise"
 ---> Running in e3084037668e
demo best practise
Removing intermediate container e3084037668e
 ---> 4588ecf9837a
Step 4/4 : ENTRYPOINT [ "/bin/sh" ]
 ---> Running in d63f460347ff
Removing intermediate container d63f460347ff
 ---> 77b52d828f21
Successfully built 77b52d828f21
Successfully tagged demo:0.0.1
  • 2nd build

Dockerfile 與 1st build 徹底一致, 命令僅修改 build tag , 從 0.0.1 到 0.0.2架構

# docker build -t demo:0.0.2 .Sending build context to Docker daemon  4.096kB
Step 1/4 : FROM nginx:1.15-alpine
 ---> 9a2868cac230
Step 2/4 : RUN echo "hello"
 ---> Using cache
 ---> 6dd2a7773bbc
Step 3/4 : RUN echo "demo best practise"
 ---> Using cache
 ---> 4588ecf9837a
Step 4/4 : ENTRYPOINT [ "/bin/sh" ]
 ---> Using cache
 ---> 77b52d828f21
Successfully built 77b52d828f21
Successfully tagged demo:0.0.2

能夠看到,ide

  1. 每層 layer 都使用 cache (---> Using cache) ,並未從新構建。
  2. 咱們能夠經過 docker image ls |grep demo 看到, demo:0.0.1 與 demo:0.0.2 的 layer hash 是相同。
    因此從根本上來講, 這兩個鏡像就是同一個鏡像,雖然都是 build 出來的。

3rd build

此次, 咱們將第三層 RUN echo "demo best practise" 變動爲 RUN echo "demo best practise 02"優化

docker build -t demo:0.0.3 .
Sending build context to Docker daemon  4.608kB
Step 1/4 : FROM nginx:1.15-alpine
 ---> 9a2868cac230
Step 2/4 : RUN echo "hello"
 ---> Using cache
 ---> 6dd2a7773bbc
Step 3/4 : RUN echo "demo best practise 02"
 ---> Running in c55f94e217bd
demo best practise 02Removing intermediate container c55f94e217bd
 ---> 46992ea04f49
Step 4/4 : ENTRYPOINT [ "/bin/sh" ]
 ---> Running in f176830cf445
Removing intermediate container f176830cf445
 ---> 2e2043b7f3cb
Successfully built 2e2043b7f3cb
Successfully tagged demo:0.0.3

能夠看到 ,ui

  1. 第二層仍然使用 cache
  2. 可是第三層已經生成了新的 hash 了
  3. 雖然第四層的操做沒有變動,可是因爲上層的鏡像已經變化了,因此第四層自己也發生了變化。操作系統

    注意: 每層在 build 的時候都是依賴於上冊 ---> Running in f176830cf445。code

4th build

第四次構建, 此次使用 --no-cache 不使用緩存, 模擬在另外一臺電腦上進行 build 。對象

# docker build -t demo:0.0.4 --no-cache .  Sending build context to Docker daemon  5.632kB
Step 1/4 : FROM nginx:1.15-alpine
 ---> 9a2868cac230
Step 2/4 : RUN echo "hello"
 ---> Running in 7ecbed95c4cdhello
Removing intermediate container 7ecbed95c4cd
 ---> a1c998781f2e
Step 3/4 : RUN echo "demo best practise 02"
 ---> Running in e90dae9440c2
demo best practise 02Removing intermediate container e90dae9440c2
 ---> 09bf3b4238b8
Step 4/4 : ENTRYPOINT [ "/bin/sh" ]
 ---> Running in 2ec19670cb14
Removing intermediate container 2ec19670cb14
 ---> 9a552fa08f73
Successfully built 9a552fa08f73
Successfully tagged demo:0.0.4

能夠看到,

  1. 雖然和 3rd build 使用的 Dockerfile 相同, 但因爲沒有緩存,每一層都是從新 build 的。
  2. 雖然 demo:0.0.3 和 demo:0.0.4 在功能上是一致的。
    可是 他們的 layer 不一樣, 從根本上來講,他們是不一樣的鏡像。

總結

Dockerfile 之外的功夫

  1. 儘可能不變的構建環境,保障 Dockerfile 在任意時間構建的時候,能夠複用已生成的 緩存層
  2. 更好的組織架構規劃,同一組或同一技術棧的同事能夠用相同的 FROM 基礎層, 以複用在生產場景中的基礎鏡像。

Dockerfile 之內的事項

  1. 須要保證, 在 Dockerfile 中,越上層的語句越穩定,越不容易變化。
  2. 在執行 ADDCOPY 時, 儘可能不要以 文件夾 做爲對象,由於文件夾中變化因子更多。儘量的將變化頻發的文件放在最下層。
  3. 使用 .dockerignore 忽略不須要的文件,以保證 context 的簡潔。
相關文章
相關標籤/搜索