成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何構(gòu)建 Golang Dockerfiles?

系統(tǒng) Linux
本文會介紹為什么 Golang 可以很好地展示這些特性,因為 Golang 可以編譯為單個二進(jìn)制文件(或一組二進(jìn)制文件)。

Docker 提供了一些出色的構(gòu)建時功能和基本映像,我們可以用它們來實現(xiàn)輕量、安全和高效的應(yīng)用程序構(gòu)建。

本文會介紹為什么 Golang 可以很好地展示這些特性,因為 Golang 可以編譯為單個二進(jìn)制文件(或一組二進(jìn)制文件)。

這篇文章的示例所關(guān)注的焦點是極簡主義。盡管這些示例很基礎(chǔ),但它們非常重要,你可以在這些概念基礎(chǔ)上為大型 Golang 項目引入更多最佳實踐,以提高安全性和效率。

我們將使用這個簡單的 main.go 來演示本文的概念:

package main  
import "fmt"
func main() {
fmt.Println("Hello Cloudreach!")
}

最少的層帶來效率最大化:最佳實踐

Docker 在 Dockerfile 文檔中一上來就強(qiáng)調(diào):盡量減少層數(shù)是一個最佳實踐!這是一個重要的概念,必須從一開始就做好。

你很容易就能寫一個包含很多層的 Dockerfile——它的語法就有這個傾向——結(jié)果你不知不覺中就會寫出很多效率低下的內(nèi)容。

最佳實踐是將構(gòu)建的相關(guān)階段分組和鏈接在一起,例如下載依賴項、供應(yīng)商文件夾集成或使用 RUN 命令設(shè)置構(gòu)建環(huán)境等階段。

你還需要考慮分組的哪些部分是可以經(jīng)常更改的,然后將它們分組到 Dockerfile 中盡可能低的層,同時把靜態(tài)構(gòu)建依賴項、構(gòu)建環(huán)境配置或應(yīng)用程序資產(chǎn)放到 Dockerfile 中盡可能上層的位置上。

每一層,更具體地說是 Dockerfile 中以指令開頭的每一行,都經(jīng)過哈希處理并建立在另一層之上,最后一個映像由“堆疊(stacked)”層構(gòu)成。

由于 Dockerfile 的每一層都是從下一層繼承的,因此構(gòu)建緩存提供了一種很好的機(jī)制,可以幫助你跳過已構(gòu)建或靜態(tài)的內(nèi)容,然后轉(zhuǎn)到你需要構(gòu)建和重新哈希的部分!

盡量縮短構(gòu)建時間是很重要的,因為高效的 CI/CD 系統(tǒng)每天都會運(yùn)行這些構(gòu)建很多次。當(dāng)團(tuán)隊規(guī)模逐漸擴(kuò)大后,這可能意味著大量的構(gòu)建工作,可能會需要很多 Jenkins worker,有時甚至需要很長時間才能集成開發(fā)人員的代碼!

Docker 有一些構(gòu)建緩存功能,它們可以顯著節(jié)省構(gòu)建時間。等待構(gòu)建的時間越短,意味著集成和自動化測試的速度也就越快,也能提升 CI/CD 流程的速度,讓你的流程足以和團(tuán)隊規(guī)模相匹配。

盡可能為應(yīng)用程序安排單獨(dú)的非 root 用戶也是很重要的。你只需要在 linux adduser 命令中使用 RUN 指令,然后在 Dockerfile 中使用 USER 指令就可以使用這個用戶來運(yùn)行二進(jìn)制文件了。

下面是使用這些最佳實踐構(gòu)造的一個最精簡的 Dockerfile main.go 示例,它只有一個基本的 main 函數(shù),沒有外部依賴項:

FROM golang:alpine  
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN go build -o main .
RUN adduser -S -D -H -h /app appuser
USER appuser
CMD ["./main"]

構(gòu)建后,生成的映像大小為 378MB:

$  docker build -t hellocloudreachmain:1.0 . -f Dockerfile.single
... (build output omitted)
$ docker images | grep hellocloudreachmain
hellocloudreachmain 1.0 d1c5090585bc Less than a second ago 378MB

盡可能使用基于 Alpine 的官方映像!它是基于 busybox 和 musl 構(gòu)建的,最輕量級的 Linux 發(fā)行版之一。與較重的發(fā)行版相比,它的容器映像體積很小,這是一個輕松提升效率的好方法。

但我們還可以進(jìn)一步簡化!這些官方映像構(gòu)建(比如golang:alpine)都包含很多層,里面含一些安全組件,用來構(gòu)建應(yīng)用程序資產(chǎn)時很方便;但是如果我們的應(yīng)用程序不需要這些層,那就不要把它們放進(jìn)去!我們需要使用其他一些 Docker 構(gòu)建功能,進(jìn)一步縮小文件體積。

下一步:多階段

當(dāng)需要在生產(chǎn)環(huán)境中運(yùn)行應(yīng)用程序時,我們需要讓容器的設(shè)計可以確保性能和安全性。我們還需要盡可能多的可移植性,以便輕松地移動容器,并使用 DockerSwarm 和 Kubernetes 之類的編排器對其進(jìn)行大規(guī)模調(diào)度。

將映像推入和拉出注冊表所需的時間應(yīng)盡量縮短。編寫用于生產(chǎn)的 Dockerfile 時,要記住的一個要點就是在最終運(yùn)行時映像中實踐極簡主義。

如果運(yùn)行的時候并不需要某樣?xùn)|西,請不要把它放進(jìn)去!

在開發(fā)環(huán)境中,有時需要一個“較重”的容器映像,也許是一個開發(fā)人員專屬的 Dockerfile,方便開發(fā)人員隨時扔進(jìn)來一些工具,和容器一起進(jìn)行調(diào)試等開發(fā)活動。也可能會附加或保留一兩個卷和活動容器交互。這些當(dāng)然都是很常見的情況!

但是,隨著容器映像沿開發(fā)管線向上移動,一定要記得把這些東西都取出來。一條正規(guī)的安全軟件供應(yīng)鏈會要求在管道中盡早構(gòu)建最終映像,對映像簽名,并將經(jīng)過正式簽名的映像推到生產(chǎn)環(huán)境的各個階段。

因此,你需要盡早在供應(yīng)鏈中構(gòu)建、驗證、集成和簽名這個最小化的映像;這是 Dockerfile 開發(fā)人員、QA 團(tuán)隊和安全工程師必須熟悉的操作!換句話說,只構(gòu)建一次,然后讓你的流程將生成的映像投入生產(chǎn)環(huán)境。

多階段構(gòu)建是實現(xiàn)這一目標(biāo)的一個好方法!多階段涉及的基本原理包括:調(diào)用一個臨時容器以簡化應(yīng)用程序的構(gòu)建,然后將構(gòu)建的資產(chǎn)從這個空間復(fù)制到只有運(yùn)行應(yīng)用所需必要組件的容器映像中。拿之前的 Dockerfile 示例來說:

FROM golang:alpine as builder  
RUN mkdir /build
ADD . /build/
WORKDIR /build
RUN go build -o main .
FROM alpine
RUN adduser -S -D -H -h /app appuser
USER appuser
COPY --from=builder /build/main /app/
WORKDIR /app
CMD ["./main"]

注意這個 Dockerfile 中的兩個 FROM 指令。我們將第一個標(biāo)記為“builder”,使用它來構(gòu)建應(yīng)用程序。

然后,我們使用第二個 FROM,這一次是從基本的“alpine”(非常輕巧?。┲刑崛〉模⑽覀儤?gòu)建的可執(zhí)行文件從該環(huán)境復(fù)制到該新環(huán)境。

這就讓映像的體積比以前小了很多!另外,“builder”容器被緩存在 docker builder 上下文中,因此可以像前面的示例一樣利用構(gòu)建緩存來提升速度!

$  docker build -t hellocloudreachmain:1.1 . -f Dockerfile.multi
... (build output omitted)
$ docker images | grep hellocloudreachmain
hellocloudreachmain 1.0 d1c5090585bc 8 minutes ago 378MB
hellocloudreachmain 1.1 ea737df5cc64 Less than a second ago 6.16MB

這個映像的大小是 6.16MB。相比 378MB 來說,體積減少的效果很明顯!

最小化整個運(yùn)行環(huán)境……從頭開始構(gòu)建!

實際上,我們在精簡之路上還可以走得更遠(yuǎn)。Golang 有很多有趣的特性,其中之一是你可以編譯為單個二進(jìn)制文件,并且在大多數(shù)情況下,你可以使用某些特殊的構(gòu)建時參數(shù)將所有相關(guān)的庫靜態(tài)編譯進(jìn)這個二進(jìn)制文件。

這樣我們就能構(gòu)建一個最小化的 Docker 容器,并減少額外的運(yùn)行時開銷,以實現(xiàn)我們所追求的出色性能、可移植性和安全性!

如果我們可以將 Golang 應(yīng)用程序編譯為單個二進(jìn)制文件,并將它靜態(tài)鏈接到依賴項上,就可以使用一個 0KB 容器來運(yùn)行這個應(yīng)用程序。這是 Docker 提供的一個特殊的基礎(chǔ)映像,稱為“scratch”。

在我們的 Docker 培訓(xùn)課程中總會遇到一個問題:所有容器內(nèi)部都裝有操作系統(tǒng)嗎?答案是否定的,就是因為有這種特殊類型!

這個映像內(nèi)部沒有關(guān)聯(lián)受支持的操作系統(tǒng)環(huán)境。它有一些特殊要求,最重要的是,主機(jī)的架構(gòu)必須支持編譯好的二進(jìn)制文件的架構(gòu)(x86、x64 等),然后,你實際得到的容器除了隔離功能和 Docker 容器的那些優(yōu)秀特性外,不向應(yīng)用程序提供任何功能或支持!盡量使用 scratch 作為基礎(chǔ)映像,將為你的應(yīng)用程序容器提供極高的簡約性和安全性水平。

FROM golang:alpine as builder  
RUN mkdir /build
ADD . /build/
WORKDIR /build
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o main .
FROM scratch
COPY --from=builder /build/main /app/
WORKDIR /app
CMD ["./main"]

在第 6 行,F(xiàn)ROM scratch 告訴 Docker 從頭開始,就像我們在上一個多階段示例中看到的那樣,但這次使用的是 0KB 臨時映像。第一個階段與之前類似,但這次我們在構(gòu)建階段使用一些編譯時參數(shù)來指示 go 編譯器將運(yùn)行時庫靜態(tài)鏈接到二進(jìn)制文件本身:

RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-extldflags "-static"' -o main.

在此示例中,最終的 Docker 映像只會包含這一個可執(zhí)行文件,而無需使用容器操作系統(tǒng)。

$ docker build -t hellocloudreachmain:1.2 . -f Dockerfile.scratch  
... (build output omitted)
$ docker images | grep hellocloudreachmain
hellocloudreachmain 1.0 d1c5090585bc 8 minutes ago 378MB
hellocloudreachmain 1.1 ea737df5cc64 4 minutes ago 6.16MB
hellocloudreachmain 1.2 bda5c99404ae 33 seconds ago 2.01MB

太棒了,生成的容器大小只有 2.01MB!與最初的 378MB 映像相比,這是一個巨大的進(jìn)步!

那么這些真的有用嗎?

$  docker run -it hellocloudreachmain:1.0  
Hello Cloudreach!
$ docker run -it hellocloudreachmain:1.1
Hello Cloudreach!
$ docker run -it hellocloudreachmain:1.2
Hello Cloudreach!

小結(jié)

我們用一個基本的 Dockerfile 舉例,然后一步步縮減最終映像的體積。通過這個簡單的練習(xí),我們很容易看到在構(gòu)建 Golang 應(yīng)用程序時,有很多選擇可以在 Docker 構(gòu)建中實踐極簡主義。

我們有很多辦法可以利用這種語言的特性,及其在編譯期間提供給開發(fā)人員的特性來減小容器的體積。由于 Golang 可以編譯為靜態(tài)鏈接的可執(zhí)行文件,因此我們能利用這類特性為運(yùn)行時剝離所有不必要的組件。

更復(fù)雜的應(yīng)用程序和構(gòu)建可能無法遵循和上面完全相同的設(shè)計模式,但是這些原理可以應(yīng)用在大多數(shù) Golang Dockerfile 上!只需花一些時間來確保自己使用行業(yè)最佳實踐正確構(gòu)建 Dockerfile,就能成功地在容器中構(gòu)建快速、安全和可擴(kuò)展的應(yīng)用程序!

責(zé)任編輯:龐桂玉 來源: 馬哥Linux運(yùn)維
相關(guān)推薦

2019-09-17 09:44:45

DockerHTMLPython

2019-10-11 10:44:30

Go語言數(shù)據(jù)庫軟件

2022-07-20 11:05:24

Dockerfilebuildpack云原生

2017-05-27 20:32:20

2023-07-03 08:52:31

容器Golang

2021-09-02 12:10:52

Go語言枚舉類型

2023-03-13 07:40:44

高并發(fā)golang

2024-02-26 00:01:01

RedisGolang應(yīng)用程序

2024-03-04 14:51:13

Golang鏡像二進(jìn)制文件

2017-11-07 06:28:11

2022-01-21 10:58:39

JavaScriptGolangPython

2023-02-21 09:45:45

Golang應(yīng)用程序

2020-10-27 18:45:45

GolangGraphQ開發(fā)

2020-12-15 11:23:09

數(shù)據(jù)驅(qū)動企業(yè)數(shù)字化

2019-09-10 13:34:30

Linux操作系統(tǒng)軟件

2017-03-01 14:30:48

存儲云私有云公有云

2017-03-03 10:18:13

存儲云APIGUI

2021-05-13 09:07:03

容器云環(huán)境鏡像

2019-07-29 08:00:18

文件容器Docker Comp

2017-04-28 11:15:26

大數(shù)據(jù)用戶畫像技術(shù)
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: avav在线看 | 久久国产精品一区 | 爱爱综合网 | www视频在线观看 | 日本黄色短片 | 欧美日韩一二区 | 国产二区视频 | 国产精品福利在线观看 | 久久国产美女视频 | 国产目拍亚洲精品99久久精品 | 免费a大片 | 性大毛片视频 | 在线免费观看黄色 | 国产韩国精品一区二区三区 | 成人黄色电影在线观看 | 欧美色综合天天久久综合精品 | 精品一级毛片 | 欧美福利 | 久久综合狠狠综合久久综合88 | 欧美日韩国产精品一区 | 免费毛片www com cn | 九九综合| 91免费在线视频 | 久草在线影 | 在线免费黄色 | 在线免费观看a级片 | 国产男女视频 | 男女视频免费 | 精品国产一区二区国模嫣然 | 三级视频国产 | 日韩有码一区 | 精品中文字幕在线 | 男人的天堂久久 | 亚洲精品中文字幕在线观看 | 日韩视频一区 | 成人精品国产免费网站 | 国产精品久久久久久久久图文区 | 神马久久春色视频 | www国产亚洲精品 | 国产不卡在线播放 | 黑人精品 |