自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

程序員如何編寫優(yōu)雅的Dockerfile

開發(fā) 開發(fā)工具
Kubernetes要從容器化開始,而容器又需要從Dockerfile開始,本文將介紹如何寫出一個優(yōu)雅的Dockerfile文件。

Kubernetes要從容器化開始,而容器又需要從Dockerfile開始,本文將介紹如何寫出一個優(yōu)雅的Dockerfile文件。

[[262928]]

文章主要內(nèi)容包括:

  • Docker容器
  • Dockerfile
  • 使用多階構建

感謝公司提供大量機器資源及時間讓我們可以實踐,感謝在此專題上不斷實踐的部分項目及人員的支持。

 

一、Docker容器

1. 容器的特點

我們都知道容器就是一個標準的軟件單元,它有以下特點:

  • 隨處運行:容器可以將代碼與配置文件和相關依賴庫進行打包,從而確保在任何環(huán)境下的運行都是一致的。
  • 高資源利用率:容器提供進程級的隔離,因此可以更加精細地設置CPU和內(nèi)存的使用率,進而更好地利用服務器的計算資源。
  • 快速擴展:每個容器都可作為單獨的進程予以運行,并且可以共享底層操作系統(tǒng)的系統(tǒng)資源,這樣一來可以加快容器的啟動和停止效率。

2. Docker容器

目前市面上的主流容器引擎有Docker、Rocket/rkt、OpenVZ/Odin等等,而獨霸一方的容器引擎就是使用最多的Docker容器引擎。

Docker容器是與系統(tǒng)其他部分隔離開的一系列進程,運行這些進程所需的所有文件都由另一個鏡像提供,從開發(fā)到測試再到生產(chǎn)的整個過程中,Linux 容器都具有可移植性和一致性。相對于依賴重復傳統(tǒng)測試環(huán)境的開發(fā)渠道,容器的運行速度要快得多,并且支持在多種主流云平臺(PaaS)和本地系統(tǒng)上部署。Docker容器很好地解決了“開發(fā)環(huán)境能正常跑,一上線就各種崩”的尷尬。

Docker容器的特點:

  • 輕量:容器是進程級的資源隔離,而虛擬機是操作系統(tǒng)級的資源隔離,所以Docker容器相對于虛擬機來說可以節(jié)省更多的資源開銷,因為Docker容器不再需要GuestOS這一層操作系統(tǒng)了。
  • 快速:容器的啟動和創(chuàng)建無需啟動GuestOS,可以實現(xiàn)秒級甚至毫秒級的啟動。
  • 可移植性:Docker容器技術是將應用及所依賴的庫和運行時的環(huán)境技術改造包成容器鏡像,可以在不同的平臺運行。
  • 自動化:容器生態(tài)中的容器編排工作(如:Kubernetes)可幫助我們實現(xiàn)容器的自動化管理。

二、Dockerfile

Dockerfile是用來描述文件的構成的文本文檔,其中包含了用戶可以在使用行調(diào)用以組合Image的所有命令,用戶還可以使用Docker build實現(xiàn)連續(xù)執(zhí)行多個命令指今行的自動構建。

通過編寫Dockerfile生磁鏡像,可以為開發(fā)、測試團隊提供基本一致的環(huán)境,從而提升開發(fā)、測試團隊的效率,不用再為環(huán)境不統(tǒng)一而發(fā)愁,同時運維也能更加方便地管理我們的鏡像。

Dockerfile的語法非常簡單,常用的只有11個:

1. 編寫優(yōu)雅地Dockerfile

編寫優(yōu)雅的Dockerfile主要需要注意以下幾點:

  • Dockerfile文件不宜過長,層級越多最終制作出來的鏡像也就越大。
  • 構建出來的鏡像不要包含不需要的內(nèi)容,如日志、安裝臨時文件等。
  • 盡量使用運行時的基礎鏡像,不需要將構建時的過程也放到運行時的Dockerfile里。

只要記住以上三點就能寫出不錯的Dockerfile。

為了方便大家了解,我們用兩個Dockerfile實例進行簡單的對比:

  1. FROM ubuntu:16.04 
  2. RUN apt-get update 
  3. RUN apt-get install -y apt-utils libjpeg-dev \      
  4. python-pip 
  5. RUN pip install --upgrade pip 
  6. RUN easy_install -U setuptools 
  7. RUN apt-get clean 
  1. FROM ubuntu:16.04 
  2. RUN apt-get update && apt-get install -y apt-utils \ 
  3.   libjpeg-dev python-pip \ 
  4.            && pip install --upgrade pip \ 
  5.       && easy_install -U setuptools \ 
  6.     && apt-get clean 

我們看***個Dockerfile,乍一看條理清晰,結構合理,似乎還不錯。再看第二個Dockerfile,緊湊,不易閱讀,為什么要這么寫?

  • ***個Dockerfile的好處是:當正在執(zhí)行的過程某一層出錯,對其進行修正后再次Build,前面已經(jīng)執(zhí)行完成的層不會再次執(zhí)行。這樣能大大減少下次Build的時間,而它的問題就是會因?qū)蛹壸兌嗔硕圭R像占用的空間也變大。
  • 第二個Dockerfile把所有的組件全部在一層解決,這樣做能一定程度上減少鏡像的占用空間,但在制作基礎鏡像的時候若其中某個組編譯出錯,修正后再次Build就相當于重頭再來了,前面編譯好的組件在一個層里,得全部都重新編譯一遍,比較消耗時間。

從下表可以看出兩個Dockerfile所編譯出來的鏡像大?。?/p>

  1. $ docker images | grep ubuntu       
  2. REPOSITORY      TAG     IMAGE ID    CREATED     SIZE                                                                                                                                    
  3. ubuntu                   16.04       9361ce633ff1  1 days ago 422MB 
  4. ubuntu                   16.04-1   3f5b979df1a9  1 days ago  412MB 

呃…. 好像并沒有特別的效果,但若Dockerfile非常長的話可以考慮減少層次,因為Dockerfile***只能有127層。

三、使用多階構建

Docker在升級到Docker 17.05之后就能支持多階構建了,為了使鏡像更加小巧,我們采用多階構建的方式來打包鏡像。在多階構建出現(xiàn)之前我們通常使用一個Dockerfile或多個Dockerfile來構建鏡像。

1. 單文件構建

在多階構建出來之前使用單個文件進行構建,單文件就是將所有的構建過程(包括項目的依賴、編譯、測試、打***程)全部包含在一個Dockerfile中之下:

  1. FROM golang:1.11.4-alpine3.8 AS build-env 
  2. ENV GO111MODULE=off 
  3. ENV GO15VENDOREXPERIMENT=1 
  4. ENV BUILDPATH=github.com/lattecake/hello 
  5. RUN mkdir -p /go/src/${BUILDPATH} 
  6. COPY ./ /go/src/${BUILDPATH} 
  7. RUN cd /go/src/${BUILDPATH} && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install –v 
  8.  
  9. CMD [/go/bin/hello] 

這種的做法會帶來一些問題:

  1. Dockerfile文件會特別長,當需要的東西越來越多的時候可維護性指數(shù)級將會下降;
  2. 鏡像層次過多,鏡像的體積會逐步增大,部署也會變得越來越慢;
  3. 代碼存在泄漏風險。

以Golang為例,它運行時不依賴任何環(huán)境,只需要有一個編譯環(huán)境,那這個編譯環(huán)境在實際運行時是沒有任務作用的,編譯完成后,那些源碼和編譯器已經(jīng)沒有任務用處了也就沒必要留在鏡像里。

 

上表可以看到,單文件構建最終占用了312MB的空間。

2.  多文件構建

在多階構建出來之前有沒有好的解決方案呢?有,比如采用多文件構建或在構建服務器上安裝編譯器,不過在構建服務器上安裝編譯器這種方法我們就不推薦了,因為在構建服務器上安裝編譯器會導致構建服務器變得非常臃腫,需要適配各個語言多個版本、依賴,容易出錯,維護成本高。所以我們只介紹多文件構建的方式。

多文件構建,其實就是使用多個Dockerfile,然后通過腳本將它們進行組合。假設有三個文件分別是:Dockerfile.run、Dockerfile.build、build.sh。

  • Dockerfile.run就是運行時程序所必須需要的一些組件的Dockerfile,它包含了最精簡的庫;
  • Dockerfile.build只是用來構建,構建完就沒用了;
  • build.sh的功能就是將Dockerfile.run和Dockerfile.build進行組成,把Dockerfile.build構建好的東西拿出來,然后再執(zhí)行Dockerfile.run,算是一個調(diào)度的角色。

Dockerfile.build

  1. FROM golang:1.11.4-alpine3.8 AS build-env 
  2. ENV GO111MODULE=off 
  3. ENV GO15VENDOREXPERIMENT=1 
  4. ENV BUILDPATH=github.com/lattecake/hello 
  5. RUN mkdir -p /go/src/${BUILDPATH} 
  6. COPY ./ /go/src/${BUILDPATH} 
  7. RUN cd /go/src/${BUILDPATH} && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install –v 

Dockerfile.run

  1. FROM alpine:latest 
  2. RUN apk –no-cache add ca-certificates 
  3. WORKDIR /root 
  4. ADD hello . 
  5. CMD ["./hello"] 

Build.sh

  1. #!/bin/sh 
  2. docker build -t –rm hello:build . -f Dockerfile.build 
  3. docker create –name extract hello:build 
  4. docker cp extract:/go/bin/hello ./hello 
  5. docker rm -f extract 
  6. docker build –no-cache -t –rm hello:run . -f Dockerfile.run 
  7. rm -rf ./hello 

執(zhí)行build.sh完成項目的構建。

從上表可以看到,多文件構建大大減小了鏡像的占用空間,但它有三個文件需要管理,維護成本也更高一些。

3. 多階構建

***我們來看看萬眾期待的多階構建。

完成多階段構建我們只需要在Dockerfile中多次使用FORM聲明,每次FROM指令可以使用不同的基礎鏡像,并且每次FROM指令都會開始新的構建,我們可以選擇將一個階段的構建結果復制到另一個階段,在最終的鏡像中只會留下***一次構建的結果,這樣就可以很容易地解決前面提到的問題,并且只需要編寫一個Dockerfile文件。這里值得注意的是:需要確保Docker的版本在17.05及以上。下面我們來說說具體操作。

在Dockerfile里可以使用as來為某一階段取一個別名”build-env”:

  1. FROM golang:1.11.2-alpine3.8 AS build-env 
  1. COPY –from=build-env /go/bin/hello /usr/bin/hello  

看一個簡單的例子:

  1. FROM golang:1.11.4-alpine3.8 AS build-env 
  2.   
  3. ENV GO111MODULE=off 
  4. ENV GO15VENDOREXPERIMENT=1 
  5. ENV GITPATH=github.com/lattecake/hello 
  6. RUN mkdir -p /go/src/${GITPATH} 
  7. COPY ./ /go/src/${GITPATH} 
  8. RUN cd /go/src/${GITPATH} && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install -v 
  9.   
  10. FROM alpine:latest 
  11. ENV apk –no-cache add ca-certificates 
  12. COPY --from=build-env /go/bin/hello /root/hello 
  13. WORKDIR /root 
  14. CMD ["/root/hello"] 

執(zhí)行docker build -t –rm hello3 .后再執(zhí)行docker images ,然后我們來看鏡像的大?。?/p>

多階構建給我們帶來很多便利,***的優(yōu)勢是在保證運行鏡像足夠小的情況下還減輕了Dockerfile的維護負擔,因此我們極力推薦使用多階構建來將你的代碼打包成Docker 鏡像。

【本文是51CTO專欄機構宜信技術學院的原創(chuàng)文章,微信公眾號“宜信技術學院( id: CE_TECH)”】

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2014-12-01 10:05:25

程序員

2022-08-11 11:09:38

線上問題程序員

2020-03-29 20:09:44

程序員技術開發(fā)

2019-05-05 15:50:39

VSCode編輯器程序員

2011-04-01 09:13:19

VB程序員

2024-05-31 07:52:18

2013-08-20 09:33:59

程序員

2009-12-03 16:50:58

Visual Basi

2024-06-24 14:19:48

2020-03-02 15:15:37

程序員工資協(xié)議

2014-07-14 11:28:41

2011-05-13 14:34:02

程序員

2020-07-27 08:34:17

程序員技術設計

2020-02-25 22:41:41

程序員技能開發(fā)者

2016-04-28 11:17:33

互動出版網(wǎng)

2010-10-18 11:18:44

程序員

2014-03-04 09:43:23

程序員外包

2014-09-22 09:42:54

程序員

2012-03-06 09:22:46

程序員

2020-04-04 20:59:28

程序員技術開發(fā)
點贊
收藏

51CTO技術棧公眾號