欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Dockerfile中multi-stage(多階段構(gòu)建)詳解

 更新時(shí)間:2018年03月12日 11:16:38   作者:sparkdev  
在2017年5月3日即將發(fā)行的 Docker 17.05.0-ce 中,Docker 官方提供了簡便的多階段構(gòu)建 (multi-stage build) 方案,下面這篇文章主要給大家介紹了關(guān)于Dockerfile中multi-stage(多階段構(gòu)建)的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。

前言

Docker的口號是Build,Ship,and Run Any App,Anywhere,在我們使用 Docker 的大部分時(shí)候,的確能感覺到其優(yōu)越性,但是往往在我們 Build 一個(gè)應(yīng)用的時(shí)候,是將我們的源代碼也構(gòu)建進(jìn)去的,這對于類似于 golang 這樣的編譯型語言肯定是不行的,因?yàn)閷?shí)際運(yùn)行的時(shí)候我只需要把最終構(gòu)建的二進(jìn)制包給你就行,把源碼也一起打包在鏡像中,需要承擔(dān)很多風(fēng)險(xiǎn),即使是腳本語言,在構(gòu)建的時(shí)候也可能需要使用到一些上線的工具,這樣無疑也增大了我們的鏡像體積。

在應(yīng)用了容器技術(shù)的軟件開發(fā)過程中,控制容器鏡像的大小可是一件費(fèi)時(shí)費(fèi)力的事情。如果我們構(gòu)建的鏡像既是編譯軟件的環(huán)境,又是軟件最終的運(yùn)行環(huán)境,這是很難控制鏡像大小的。所以常見的配置模式為:分別為軟件的編譯環(huán)境和運(yùn)行環(huán)境提供不同的容器鏡像。比如為編譯環(huán)境提供一個(gè) Dockerfile.build,用它構(gòu)建的鏡像包含了編譯軟件需要的所有內(nèi)容,比如代碼、SDK、工具等等。同時(shí)為軟件的運(yùn)行環(huán)境提供另外一個(gè)單獨(dú)的 Dockerfile,它從 Dockerfile.build 中獲得編譯好的軟件,用它構(gòu)建的鏡像只包含運(yùn)行軟件所必須的內(nèi)容。這種情況被稱為構(gòu)造者模式(builder pattern),本文將介紹如何通過 Dockerfile 中的 multi-stage 來解決構(gòu)造者模式帶來的問題。

常見的容器鏡像構(gòu)建過程

比如我們創(chuàng)建了一個(gè) GO 語言編寫了一個(gè)檢查頁面中超級鏈接的程序 app.go(請從 sparkdev  (本地下載)獲取本文相關(guān)的代碼):

package main
import (
 "encoding/json"
 "fmt"
 "log"
 "net/http"
 "net/url"
 "os"
 "strings"
 "golang.org/x/net/html"
)
type scrapeDataStore struct {
 Internal int `json:"internal"`
 External int `json:"external"`
}
func isInternal(parsedLink *url.URL, siteUrl *url.URL, link string) bool {
 return parsedLink.Host == siteUrl.Host || strings.Index(link, "#") == 0 || len(parsedLink.Host) == 0
}
func main() {
 urlIn := os.Getenv("url")
 if len(urlIn) == 0 {
 urlIn = "https://www.cnblogs.com/"
 }
 resp, err := http.Get(urlIn)
 scrapeData := &scrapeDataStore{}
 tokenizer := html.NewTokenizer(resp.Body)
 end := false
 for {
 tt := tokenizer.Next()
 switch {
 case tt == html.StartTagToken:
 token := tokenizer.Token()
 switch token.Data {
 case "a":
 for _, attr := range token.Attr {
  if attr.Key == "href" {
  link := attr.Val
  parsedLink, parseLinkErr := url.Parse(link)
  if parseLinkErr == nil {
  if isInternal(parsedLink, siteUrl, link) {
  scrapeData.Internal++
  } else {
  scrapeData.External++
  }
  }
  if parseLinkErr != nil {
  fmt.Println("Can't parse: " + token.Data)
  }
  }
 }
 break
 }
 case tt == html.ErrorToken:
 end = true
 break
 }
 if end {
 break
 }
 }
 data, _ := json.Marshal(&scrapeData)
 fmt.Println(string(data))
}

下面我們通過容器來構(gòu)建它,并把它部署到生產(chǎn)型的容器鏡像中。

首先構(gòu)建編譯應(yīng)用程序的鏡像:

FROM golang:1.7.3
WORKDIR /go/src/github.com/sparkdevo/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

把上面的內(nèi)容保存到 Dockerfile.build 文件中。

接著把構(gòu)建好的應(yīng)用程序部署到生產(chǎn)環(huán)境用的鏡像中:

FROM alpine:latest 
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"] 

把上面的內(nèi)容保存到 Dockerfile 文件中。

最后需要使用一個(gè)腳本把整個(gè)構(gòu)建過程整合起來:

#!/bin/sh
echo Building sparkdevo/href-counter:build
# 構(gòu)建編譯應(yīng)用程序的鏡像
docker build --no-cache -t sparkdevo/href-counter:build . -f Dockerfile.build
# 創(chuàng)建應(yīng)用程序
docker create --name extract sparkdevo/href-counter:build
# 拷貝編譯好的應(yīng)用程序
docker cp extract:/go/src/github.com/sparkdevo/href-counter/app ./app
docker rm -f extract

echo Building sparkdevo/href-counter:latest
# 構(gòu)建運(yùn)行應(yīng)用程序的鏡像
docker build --no-cache -t sparkdevo/href-counter:latest .

把上面的內(nèi)容保存到 build.sh 文件中。這個(gè)腳本會(huì)先創(chuàng)建出一個(gè)容器來構(gòu)建應(yīng)用程序,然后再創(chuàng)建最終運(yùn)行應(yīng)用程序的鏡像。

把 app.go、Dockerfile.build、Dockerfile 和 build.sh 放在同一個(gè)目錄下,然后進(jìn)入這個(gè)目錄執(zhí)行 build.sh 腳本進(jìn)行構(gòu)建。構(gòu)建后的容器鏡像大?。?/p>

從上圖中我們可以觀察到,用于編譯應(yīng)用程序的容器鏡像大小接近 700M,而用于生產(chǎn)環(huán)境的容器鏡像只有 10.3 M,這樣的大小在網(wǎng)絡(luò)間傳輸?shù)男适呛芨叩摹?/p>

運(yùn)行下面的命令可以檢查我們構(gòu)建的容器是否可以正常的工作:

$ docker run -e url=https://www.cnblogs.com/ sparkdevo/href-counter:latest
$ docker run -e url=http://www.cnblogs.com/sparkdev/ sparkdevo/href-counter:latest


OK,我們寫的程序正確的統(tǒng)計(jì)了博客園首頁和筆者的首頁中超級鏈接的情況。

采用上面的構(gòu)建過程,我們需要維護(hù)兩個(gè) Dockerfile 文件和一個(gè)腳本文件 build.sh。能不能簡化一些呢? 下面我們看看 docker 針對這種情況提供的解決方案:multi-stage。

在 Dockerfile 中使用 multi-stage

multi-stage 允許我們在 Dockerfile 中完成類似前面 build.sh 腳本中的功能,每個(gè) stage 可以理解為構(gòu)建一個(gè)容器鏡像,后面的 stage 可以引用前面 stage 中創(chuàng)建的鏡像。所以我們可以使用下面單個(gè)的 Dockerfile 文件實(shí)現(xiàn)前面的需求:

FROM golang:1.7.3
WORKDIR /go/src/github.com/sparkdevo/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/sparkdevo/href-counter/app .
CMD ["./app"]

把上面的內(nèi)容保存到文件 Dockerfile.multi 中。這個(gè) Dockerfile 文件的特點(diǎn)是同時(shí)存在多個(gè) FROM 指令,每個(gè) FROM 指令代表一個(gè) stage 的開始部分。我們可以把一個(gè) stage 的產(chǎn)物拷貝到另一個(gè) stage 中。本例中的第一個(gè) stage 完成了應(yīng)用程序的構(gòu)建,內(nèi)容和前面的 Dockerfile.build 是一樣的。第二個(gè) stage 中的 COPY 指令通過 --from=0 引用了第一個(gè) stage ,并把應(yīng)用程序拷貝到了當(dāng)前 stage 中。接下來讓我們編譯新的鏡像:

$ docker build --no-cache -t sparkdevo/href-counter:multi . -f Dockerfile.multi

這次使用 href-counter:multi 鏡像運(yùn)行應(yīng)用:

$ docker run -e url=https://www.cnblogs.com/ sparkdevo/href-counter:multi
$ docker run -e url=http://www.cnblogs.com/sparkdev/ sparkdevo/href-counter:multi


結(jié)果和之前是一樣的。那么新生成的鏡像有沒有特別之處呢:

好吧,從上圖我們可以看到,除了 sparkdevo/href-counter:multi 鏡像,還生成了一個(gè)匿名的鏡像。因此,所謂的 multi-stage 不過時(shí)多個(gè) Dockerfile 的語法糖罷了。但是這個(gè)語法糖還好很誘人的,現(xiàn)在我們維護(hù)一個(gè)結(jié)構(gòu)簡潔的 Dockerfile 文件就可以了!

使用命名的 stage

在上面的例子中我們通過 --from=0 引用了 Dockerfile 中第一個(gè) stage,這樣的做法會(huì)讓 Dockerfile 變得不容易閱讀。其實(shí)我們是可以為 stage 命名的,然后就可以通過名稱來引用 stage 了。下面是改造后的 Dockerfile.mult 文件:

FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/sparkdevo/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/sparkdevo/href-counter/app .
CMD ["./app"]

我們把第一個(gè) stage 使用 as 語法命名為 builder,然后在后面的 stage 中通過名稱 builder 進(jìn)行引用 --from=builder。通過使用命名的 stage, Dockerfile 更容易閱讀了。

總結(jié)

Dockerfile 中的 multi-stage 雖然只是些語法糖,但它確實(shí)為我們帶來了很多便利。尤其是減輕了 Dockerfile 維護(hù)者的負(fù)擔(dān)(要知道實(shí)際生產(chǎn)中的 Dockerfile 可不像 demo 中的這么簡單)。需要注意的是舊版本的 docker 是不支持 multi-stage 的,只有 17.05 以及之后的版本才開始支持。好了,是不是該去升級你的 docker 版本了?

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

參考:

相關(guān)文章

  • 詳解使用export/import導(dǎo)出和導(dǎo)入docker容器

    詳解使用export/import導(dǎo)出和導(dǎo)入docker容器

    本篇文章主要介紹了詳解使用export/import導(dǎo)出和導(dǎo)入docker容器,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • Docker run流程及鏡像的基本命令詳解

    Docker run流程及鏡像的基本命令詳解

    本文主要介紹了Docker中run流程及鏡像的基本命令,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 利用Docker?運(yùn)行?python?簡單程序

    利用Docker?運(yùn)行?python?簡單程序

    這篇文章主要介紹了利用Docker?運(yùn)行?python?簡單程序,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-04-04
  • 詳解用Docker搭建Laravel和Vue項(xiàng)目的開發(fā)環(huán)境

    詳解用Docker搭建Laravel和Vue項(xiàng)目的開發(fā)環(huán)境

    這篇文章主要介紹了詳解用Docker搭建Laravel和Vue項(xiàng)目的開發(fā)環(huán)境,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • 一步步教你用docker部署postgreSQL數(shù)據(jù)庫

    一步步教你用docker部署postgreSQL數(shù)據(jù)庫

    這篇文章主要給大家介紹了關(guān)于如何使用docker部署postgreSQL數(shù)據(jù)庫的相關(guān)資料,PostgreSQL是一款功能豐富的關(guān)系型數(shù)據(jù)庫,類似于MySQL,它也是受歡迎程度非常高的,需要的朋友可以參考下
    2023-11-11
  • 解決docker與vmware的沖突問題

    解決docker與vmware的沖突問題

    這篇文章主要介紹了解決docker與vmware的沖突問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • WIN10系統(tǒng)和Docker內(nèi)部容器IP互通方式

    WIN10系統(tǒng)和Docker內(nèi)部容器IP互通方式

    這篇文章主要介紹了WIN10系統(tǒng)和Docker內(nèi)部容器IP互通方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • 基于docker的caffe環(huán)境搭建方法

    基于docker的caffe環(huán)境搭建方法

    這篇文章主要介紹了基于docker的caffe環(huán)境搭建方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • 淺談Docker consul的容器服務(wù)更新與發(fā)現(xiàn)

    淺談Docker consul的容器服務(wù)更新與發(fā)現(xiàn)

    本文主要介紹了淺談Docker consul的容器服務(wù)更新與發(fā)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 教你使用Docker搭建gitlab社區(qū)漢化版的詳細(xì)過程

    教你使用Docker搭建gitlab社區(qū)漢化版的詳細(xì)過程

    很多朋友不太清楚使用Docker搭建gitlab社區(qū)漢化版的過程,總是容易出現(xiàn)錯(cuò)誤,今天小編抽空給大家分享使用Docker搭建gitlab社區(qū)漢化版的詳細(xì)過程,一起看看吧
    2021-09-09

最新評論