小編給大家分享一下Docker中Dockerfile多階段構(gòu)建原理及使用場景的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
成都創(chuàng)新互聯(lián)公司專注于漳縣網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供漳縣營銷型網(wǎng)站建設(shè),漳縣網(wǎng)站制作、漳縣網(wǎng)頁設(shè)計(jì)、漳縣網(wǎng)站官網(wǎng)定制、重慶小程序開發(fā)服務(wù),打造漳縣網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供漳縣網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。在17.05版本之前的Docker,只允許Dockerfile中出現(xiàn)一個FROM指令,這得從鏡像的本質(zhì)說起。
之前我們提到,你可以簡單理解Docker的鏡像是一個壓縮文件,其中包含了你需要的程序和一個文件系統(tǒng)。其實(shí)這樣說是不嚴(yán)謹(jǐn)?shù)?,Docker鏡像并非只是一個文件,而是由一堆文件組成,最主要的文件是 層。
Dockerfile 中,大多數(shù)指令會生成一個層,比如下方的兩個例子:
# 示例一,foo 鏡像的Dockerfile# 基礎(chǔ)鏡像中已經(jīng)存在若干個層了 FROM ubuntu:16.04 # RUN指令會增加一層,在這一層中,安裝了 git 軟件 RUN apt-get update \ && apt-get install -y --no-install-recommends git \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
# 示例二,bar 鏡像的Dockerfile FROM foo # RUN指令會增加一層,在這一層中,安裝了 nginx RUN apt-get update \ && apt-get install -y --no-install-recommends nginx \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
假設(shè)基礎(chǔ)鏡像 ubuntu:16.04
已經(jīng)存在5層,使用第一個Dockerfile打包成鏡像 foo,則foo有6層,又使用第二個Dockerfile打包成鏡像bar,則bar中有7層。
如果 ubuntu:16.04
等其他鏡像不算,如果系統(tǒng)中只存在 foo 和 bar 兩個鏡像,那么系統(tǒng)中一共保存了多少層呢?
是7層,并非13層,這是因?yàn)?,foo和bar共享了6層。層的共享機(jī)制可以節(jié)約大量的磁盤空間和傳輸帶寬,比如你本地已經(jīng)有了foo鏡像,又從鏡像倉庫中拉取bar鏡像時,只拉取本地所沒有的最后一層就可以了,不需要把整個bar鏡像連根拉一遍。但是層共享是怎樣實(shí)現(xiàn)的呢?
原來,Docker鏡像的每一層只記錄文件變更,在容器啟動時,Docker會將鏡像的各個層進(jìn)行計(jì)算,最后生成一個文件系統(tǒng),這個被稱為 聯(lián)合掛載。對此感興趣的話可以進(jìn)入了解一下 AUFS
。
Docker的各個層是有相關(guān)性的,在聯(lián)合掛載的過程中,系統(tǒng)需要知道在什么樣的基礎(chǔ)上再增加新的文件。那么這就要求一個Docker鏡像只能有一個起始層,只能有一個根。所以,Dockerfile中,就只允許一個 FROM
指令。因?yàn)槎鄠€ FROM
指令會造成多根,則是無法實(shí)現(xiàn)的。但為什么 Docker 17.05 版本以后允許 Dockerfile支持多個 FROM
指令了呢,莫非已經(jīng)支持了多根?
多個 FROM 指令并不是為了生成多根的層關(guān)系,最后生成的鏡像,仍以最后一條 FROM 為準(zhǔn),之前的 FROM 會被拋棄,那么之前的FROM 又有什么意義呢?
每一條 FROM 指令都是一個構(gòu)建階段,多條 FROM 就是多階段構(gòu)建,雖然最后生成的鏡像只能是最后一個階段的結(jié)果,但是,能夠?qū)⑶爸秒A段中的文件拷貝到后邊的階段中,這就是多階段構(gòu)建的大意義。
大的使用場景是將編譯環(huán)境和運(yùn)行環(huán)境分離,比如,之前我們需要構(gòu)建一個Go語言程序,那么就需要用到go命令等編譯環(huán)境,我們的Dockerfile可能是這樣的:
# Go語言環(huán)境基礎(chǔ)鏡像 FROM golang:1.10.3 # 將源碼拷貝到鏡像中 COPY server.go /build/ # 指定工作目錄 WORKDIR /build # 編譯鏡像時,運(yùn)行 go build 編譯生成 server 程序 RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server # 指定容器運(yùn)行時入口程序 server ENTRYPOINT ["/build/server"]
基礎(chǔ)鏡像 golang:1.10.3
是非常龐大的,因?yàn)槠渲邪怂械腉o語言編譯工具和庫,而運(yùn)行時候我們僅僅需要編譯后的 server
程序就行了,不需要編譯時的編譯工具,最后生成的大體積鏡像就是一種浪費(fèi)。
使用脈沖云的解決辦法是將程序編譯和鏡像打包分開,使用 脈沖云 的編譯構(gòu)建服務(wù),選擇增加構(gòu)Go語言構(gòu)建工具,然后在構(gòu)建步驟中編譯。
最后將編譯接口拷貝到鏡像中就行了,那么Dockerfile的基礎(chǔ)鏡像并不需要包含Go編譯環(huán)境:
# 不需要Go語言編譯環(huán)境 FROM scratch # 將編譯結(jié)果拷貝到容器中 COPY server /server # 指定容器運(yùn)行時入口程序 server ENTRYPOINT ["/server"]
提示:
scratch
是內(nèi)置關(guān)鍵詞,并不是一個真實(shí)存在的鏡像。FROM scratch
會使用一個完全干凈的文件系統(tǒng),不包含任何文件。 因?yàn)镚o語言編譯后不需要運(yùn)行時,也就不需要安裝任何的運(yùn)行庫。FROM scratch
可以使得最后生成的鏡像最小化,其中只包含了 server 程序。
在 Docker 17.05版本以后,就有了新的解決方案,直接一個Dockerfile就可以解決:
# 編譯階段 FROM golang:1.10.3 COPY server.go /build/ WORKDIR /build RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server # 運(yùn)行階段 FROM scratch # 從編譯階段的中拷貝編譯結(jié)果到當(dāng)前鏡像中 COPY --from=0 /build/server / ENTRYPOINT ["/server"]Copy
這個 Dockerfile 的玄妙之處就在于 COPY 指令的 --from=0
參數(shù),從前邊的階段中拷貝文件到當(dāng)前階段中,多個FROM語句時,0代表第一個階段。除了使用數(shù)字,我們還可以給階段命名,比如:
# 編譯階段 命名為 builder FROM golang:1.10.3 as builder # ... 省略 # 運(yùn)行階段 FROM scratch # 從編譯階段的中拷貝編譯結(jié)果到當(dāng)前鏡像中 COPY --from=builder /build/server /
更為強(qiáng)大的是,COPY --from
不但可以從前置階段中拷貝,還可以直接從一個已經(jīng)存在的鏡像中拷貝。比如,
FROM ubuntu:16.04 COPY --from=quay.io/coreos/etcd:v3.3.9 /usr/local/bin/etcd /usr/local/bin/
我們直接將etcd鏡像中的程序拷貝到了我們的鏡像中,這樣,在生成我們的程序鏡像時,就不需要源碼編譯etcd了,直接將官方編譯好的程序文件拿過來就行了。
有些程序要么沒有apt源,要么apt源中的版本太老,要么干脆只提供源碼需要自己編譯,使用這些程序時,我們可以方便地使用已經(jīng)存在的Docker鏡像作為我們的基礎(chǔ)鏡像。但是我們的軟件有時候可能需要依賴多個這種文件,我們并不能同時將 nginx 和 etcd 的鏡像同時作為我們的基礎(chǔ)鏡像(不支持多根),這種情況下,使用 COPY --from
就非常方便實(shí)用了。
看完了這篇文章,相信你對“Docker中Dockerfile多階段構(gòu)建原理及使用場景的示例分析”有了一定的了解,如果想了解更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司行業(yè)資訊頻道,感謝各位的閱讀!
網(wǎng)站標(biāo)題:Docker中Dockerfile多階段構(gòu)建原理及使用場景的示例分析-創(chuàng)新互聯(lián)
分享網(wǎng)址:http://jinyejixie.com/article30/dchipo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、用戶體驗(yàn)、商城網(wǎng)站、營銷型網(wǎng)站建設(shè)、網(wǎng)站維護(hù)、小程序開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)