亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Docker與Golang的巧妙結(jié)合

 更新時(shí)間:2016年10月24日 09:22:17   投稿:lqh  
這篇文章主要介紹了Docker與Golang的巧妙結(jié)合的相關(guān)資料,需要的朋友可以參考下

Docker與Golang的巧妙結(jié)合

【編者的話】這是一個(gè)展示在使用Go語(yǔ)言時(shí)如何讓Docker更有用的提示與技巧的簡(jiǎn)輯。例如,如何使用不同版本的Go工具鏈來(lái)編譯Go代碼,如何交叉編譯到不同的平臺(tái)(并且測(cè)試結(jié)果!),或者如何制作真正小的容器鏡像。

下面的文章假定你已經(jīng)安裝了Docker。不必是最新版本(這篇文章不會(huì)使用Docker任何花哨的功能)。
沒有g(shù)o的Go

...意思是:“不用安裝go就能使用Go”

如果你寫Go代碼,或者你對(duì)Go語(yǔ)言有一點(diǎn)點(diǎn)興趣,你肯定要安裝了Go編譯器和Go工具鏈,所以你可能想知道:“重點(diǎn)是什么?”;但有些情況下,你想不安裝Go就來(lái)編譯Go。

  1. 機(jī)器上依舊有老版本Go 1.2(你不能或不想更新),不得不使用這個(gè)代碼庫(kù),需要一個(gè)高版本的工具鏈。
  2. 想使用Go1.5的交叉編譯功能(例如,確保能從一個(gè)Linux系統(tǒng)創(chuàng)建操作系統(tǒng)X的二進(jìn)制文件)。
  3. 想擁有多版本的Go,但不想完全弄亂系統(tǒng)。
  4. 想100%確定項(xiàng)目和它所有的依賴,下載,建立和運(yùn)行在一個(gè)純凈的系統(tǒng)上。

如果遇到上述情況,找Docker來(lái)解決!

在容器里編譯一個(gè)程序

當(dāng)你安裝了Go,你可以執(zhí)行g(shù)o get -v github.com/user/repo來(lái)下載,創(chuàng)建和安裝一個(gè)庫(kù)。(-v只是信息顯示,如果你喜歡工具鏈快速和靜默地運(yùn)行,可以將它移除!)

你也可以執(zhí)行g(shù)o get github.com/user/repo/...來(lái)下載,創(chuàng)建和安裝那個(gè)repo(包括庫(kù)和二進(jìn)制文件)里面所有的東西。

我們可以在一個(gè)容器里面這樣做!

試試這個(gè):

docker run golang go get -v github.com/golang/example/hello/...

這將拉取golang鏡像(除非你已經(jīng)有了,那它會(huì)馬上啟動(dòng)),并且創(chuàng)建一個(gè)基于它的容器。在那個(gè)容器里,go會(huì)下載一個(gè)“hello world”的例子,創(chuàng)建它,安裝它。但它會(huì)把它安裝到這個(gè)容器里……我們現(xiàn)在怎么運(yùn)行那個(gè)程序呢?

在容器里運(yùn)行程序

一個(gè)辦法是提交我們剛剛創(chuàng)建的容器,即,打包它到一個(gè)新的鏡像:

docker commit $(docker ps -lq) awesomeness

注意:docker ps –lq輸出最后一個(gè)執(zhí)行的容器的ID(只有ID?。?。如果你是機(jī)器的唯一用戶,并且你從上一個(gè)命令開始沒有創(chuàng)建另一個(gè)容器,那這個(gè)容器就是你剛剛創(chuàng)建的“hello world”的例子。

現(xiàn)在,可以用剛剛構(gòu)建的鏡像創(chuàng)建容器來(lái)運(yùn)行程序:

docker run awesomeness hello

輸出會(huì)是Hello, Go examples!。

閃光點(diǎn)

當(dāng)用docker commit構(gòu)建鏡像時(shí),可以用--change標(biāo)識(shí)指定任意Dockerfile命令。例如,可以使用一個(gè)CMD或者ENTRYPOINT命令以便docker run awesomeness自動(dòng)執(zhí)行hello。

在一次性容器上運(yùn)行

如果不想創(chuàng)建額外的鏡像只想運(yùn)行這個(gè)Go程序呢?

使用:

docker run --rm golang sh -c \
"go get github.com/golang/example/hello/... && exec hello"

等等,那些花哨的東西是什么?

  1. --rm 告訴Docker CLI一旦容器退出,就自動(dòng)發(fā)起一個(gè)docker rm命令。那樣,不會(huì)留下任何東西。
  2. 使用shell邏輯運(yùn)算符&&把創(chuàng)建步驟(go get)和執(zhí)行步驟(exec hello)聯(lián)接在一起。如果不喜歡shell,&&意思是“與”。它允許第一部分go get...,并且如果(而且僅僅是如果?。┠遣糠诌\(yùn)行成功,它將執(zhí)行第二部分(exec hello)。如果你想知道為什么這樣:它像一個(gè)懶惰的and計(jì)算器,只有當(dāng)左邊的值是true才計(jì)算右邊的。
  3. 傳遞命令到sh –c,因?yàn)槿绻呛?jiǎn)單的做docker run golang "go get ... && hello",Docker將試著執(zhí)行名為go SPACE get SPACE etc的程序。并且那不會(huì)起作用。因此,我們啟動(dòng)一個(gè)shell,并讓shell執(zhí)行命令序列。
  4. 使用exec hello而不是hello:這將使用hello程序替代當(dāng)前的進(jìn)程(我們剛才啟動(dòng)的shell)。這確保hello在容器里是PID 1。而不是shell的是PID 1而hello作為一個(gè)子進(jìn)程。這對(duì)這個(gè)微小的例子毫無(wú)用處,但是當(dāng)運(yùn)行更有用的程序,這將允許它們正確地接收外部信號(hào),因?yàn)橥獠啃盘?hào)是發(fā)送給容器里的PID 1。你可能會(huì)想,什么信號(hào)?。亢玫睦邮莇ocker stop,發(fā)送SIGTERM給容器的PID 1。

使用不同版本的Go

當(dāng)使用golang鏡像,Docker擴(kuò)展為golang:latest,將(像你所猜的)映射到Docker Hub上的最新可用版本。

如果想用一個(gè)特定的Go版本,很容易:在鏡像名字后面用那個(gè)版本做標(biāo)簽指定它。

例如,想用Go 1.5,修改上面的例子,用golang:1.5替換golang:

docker run --rm golang:1.5 sh -c \
"go get github.com/golang/example/hello/... && exec hello"

你能在Docker Hub的Golang鏡像頁(yè)面上看到所有可用的版本(和變量)。

在系統(tǒng)上安裝

好了,如果想在系統(tǒng)上運(yùn)行編譯好的程序,而不是一個(gè)容器呢?我們將復(fù)制這個(gè)編譯了的二進(jìn)制文件到容器外面。注意,僅當(dāng)容器架構(gòu)和主機(jī)架構(gòu)匹配的時(shí)候,才會(huì)起作用;換言之,如果在Linux上運(yùn)行Docker。(我排除的可能是運(yùn)行Windows容器的人?。?/p>

最容易在容器外獲得二進(jìn)制文件的方法是映射$GOPATH/bin目錄到一個(gè)本地目錄,在golang容器里,$GOPATH是/go.所以我們可以如下操作:

docker run -v /tmp/bin:/go/bin \
golang go get github.com/golang/example/hello/...
/tmp/bin/hello

如果在Linux上,將看到Hello, Go examples!消息。但如果是,例如在Mac上,可能會(huì)看到:
-bash:

/tmp/test/hello: cannot execute binary file

我們又能做什么呢?

交叉編譯

Go 1.5具備優(yōu)秀的開箱即用交叉編譯能力,所以如果你的容器操作系統(tǒng)和/或架構(gòu)和你的系統(tǒng)不匹配,根本不是問(wèn)題!

開啟交叉編譯,需要設(shè)置GOOS和/或GOARCH。

例如,假設(shè)在64位的Mac上:

docker run -e GOOS=darwin -e GOARCH=amd64 -v /tmp/crosstest:/go/bin \
golang go get github.com/golang/example/hello/...

交叉編譯的輸出不是直接在$GOPATH/bin,而是在$GOPATH/bin/$GOOS_$GOARCH.。換言之,想運(yùn)行程序,得執(zhí)行/tmp/crosstest/darwin_amd64/hello.。

直接安裝到$PATH

如果在Linux上,甚至可以直接安裝到系統(tǒng)bin目錄:

docker run -v /usr/local/bin:/go/bin \
golang get github.com/golang/example/hello/...

然而,在Mac上,嘗試用/usr作為一個(gè)卷將不能掛載Mac的文件系統(tǒng)到容器。會(huì)掛載Moby VM(小Linux VM藏在工具欄Docker圖標(biāo)的后面)的/usr目錄。(譯注:目前Docker for Mac版本可以自定義設(shè)置掛載路徑)

但可以使用/tmp或者在你的home目錄下的什么其它目錄,然后從這里復(fù)制。

創(chuàng)建依賴鏡像

我們用這種技術(shù)產(chǎn)生的Go二進(jìn)制文件是靜態(tài)鏈接的。這意味著所有需要運(yùn)行的代碼包括所有依賴都被嵌入了。動(dòng)態(tài)鏈接的程序與之相反,不包含一些基本的庫(kù)(像“l(fā)ibc”)并且使用系統(tǒng)范圍的復(fù)制,是在運(yùn)行時(shí)確定的。

這意味著可以在容器里放棄Go編譯好的程序,沒有別的,并且它會(huì)運(yùn)行。

我們?cè)囋嚕?br />

scratch鏡像

Docker生態(tài)系統(tǒng)有一個(gè)特殊的鏡像:scratch.這是一個(gè)空鏡像。它不需要被創(chuàng)建或者下載,因?yàn)槎x的就是空的。

給新的Go依賴鏡像創(chuàng)建一個(gè)新的空目錄。

在這個(gè)新目錄,創(chuàng)建下面的Dockerfile:

FROM scratch
COPY ./hello /hello
ENTRYPOINT ["/hello"]

這意味著:從scratch開始(一個(gè)空鏡像),增加hello文件到鏡像的根目錄,*定義hello程序?yàn)閱?dòng)這個(gè)容器后默認(rèn)運(yùn)行的程序。

然后,產(chǎn)生hello二進(jìn)制文件如下:

docker run -v $(pwd):/go/bin --rm \
golang go get github.com/golang/example/hello/...

注意:不需要設(shè)置GOOS和GOARCH,正因?yàn)?,想要一個(gè)運(yùn)行在Docker容器里的二進(jìn)制文件,不是在主機(jī)上。所以不用設(shè)置這些變量!

然后,創(chuàng)建鏡像:

docker build -t hello .

測(cè)試它:

docker run hello

(將顯示“Hello, Go examples!”)

最后但不重要,檢查鏡像的大?。?br /> docker images hello

如果一切做得正確,這個(gè)鏡像大約2M。相當(dāng)好!
構(gòu)建東西而不推送到Github

當(dāng)然,如果不得不推送到GitHub,每次編譯都會(huì)浪費(fèi)很多時(shí)間。

想在一個(gè)代碼段上工作并在容器中創(chuàng)建它時(shí),可以在golang容器里掛載一個(gè)本地目錄到/go。所以$GOPATH是持久調(diào)用:docker run -v $HOME/go:/go golang ....

但也可以掛載本地目錄到特定的路徑上,來(lái)“重載”一些包(那些在本地編輯的)。這是一個(gè)完整的例子:

# Adapt the two following environment variables if you are not running on a Mac
export GOOS=darwin GOARCH=amd64
mkdir go-and-docker-is-love
cd go-and-docker-is-love
git clone git://github.com/golang/example
cat example/hello/hello.go
sed -i .bak s/olleH/eyB/ example/hello/hello.go
docker run --rm \
-v $(pwd)/example:/go/src/github.com/golang/example \
-v $(pwd):/go/bin/${GOOS}_${GOARCH} \
-e GOOS -e GOARCH \
golang go get github.com/golang/example/hello/...
./hello
# Should display "Bye, Go examples!" 

網(wǎng)絡(luò)包和CGo的特殊情況

進(jìn)入真實(shí)的Go代碼世界前,必須承認(rèn)的是:在二進(jìn)制文件上有一點(diǎn)點(diǎn)偏差。如果在使用CGo,或如果在使用net包,Go鏈接器將生成一個(gè)動(dòng)態(tài)庫(kù)。這種情況下,net包(里面確實(shí)有許多有用的Go程序?。?,罪魁禍?zhǔn)资荄NS解析。大多數(shù)系統(tǒng)都有一個(gè)花哨的,模塊化的名稱解析系統(tǒng)(像名稱服務(wù)切換),它依賴于插件,技術(shù)上,是動(dòng)態(tài)庫(kù)。默認(rèn)地,Go將嘗試使用它;這樣,它將產(chǎn)生動(dòng)態(tài)庫(kù)。

我們?cè)趺唇鉀Q?

重用另一個(gè)版本的libc

一個(gè)解決方法是用一個(gè)基礎(chǔ)鏡像,有那些程序功能所必需的庫(kù)。幾乎任何“正規(guī)”基于GNU libc的Linux發(fā)行版都能做到。所以,例如,使用FROM debian或FROM fedora,替代FROM scratch?,F(xiàn)在結(jié)果鏡像會(huì)比原來(lái)大一些;但至少,大出來(lái)的這一點(diǎn)將和系統(tǒng)里其它鏡像共享。

注意:這種情況不能使用Alpine,因?yàn)锳lpine是使用musl庫(kù)而不是GNU libc。

使用自己的libc

另一個(gè)解決方案是像做手術(shù)般地提取需要的文件,用COPY替換容器里的。結(jié)果容器會(huì)小。然而,這個(gè)提取過(guò)程困難又繁瑣,太多更深的細(xì)節(jié)要處理。

如果想自己看,看看前面提到的ldd和名稱服務(wù)切換插件。

用netgo生成靜態(tài)二進(jìn)制文件

我們也可以指示Go不用系統(tǒng)的libc,用本地DNS解析代替Go的netgo。

要使用它,只需在go get選項(xiàng)加入-tags netgo -installsuffix netgo。

-tags netgo指示工具鏈?zhǔn)褂胣etgo。

-installsuffix netgo確保結(jié)果庫(kù)(任何)被一個(gè)不同的,非默認(rèn)的目錄所替代。如果做多重go get(或go build)調(diào)用,這將避免

代碼創(chuàng)建和用不用netgo之間的沖突。如果像目前我們講到的這樣,在容器里創(chuàng)建,是完全沒有必要的。因?yàn)檫@個(gè)容器里面永遠(yuǎn)沒有其他Go代碼要編譯。但它是個(gè)好主意,習(xí)慣它,或至少知道這個(gè)標(biāo)識(shí)存在。

SSL證書的特殊情況

還有一件事,你會(huì)擔(dān)心,你的代碼必須驗(yàn)證SSL證書;例如,通過(guò)HTTPS聯(lián)接外部API。這種情況,需要將根證書也放入容器里,因?yàn)镚o不會(huì)捆綁它們到二進(jìn)制文件里。
安裝SSL證書

再次,有很多可用的選擇,但最簡(jiǎn)單的是使用一個(gè)已經(jīng)存在的發(fā)布里面的包。

Alpine是一個(gè)好的選擇,因?yàn)樗浅P O旅娴腄ockerfile將給你一個(gè)小的基礎(chǔ)鏡像,但捆綁了一個(gè)過(guò)期的跟證書:

FROM alpine:3.4
RUN apk add --no-cache ca-certificates apache2-utils

來(lái)看看吧,結(jié)果鏡像只有6MB!

注意:--no-cache選項(xiàng)告訴apk(Alpine包管理器)從Alpine的鏡像發(fā)布上獲取可用包的列表,不保存在磁盤上。你可能會(huì)看到Dockerfiles做這樣的事apt-get update && apt-get install ... && rm -rf /var/cache/apt/*;這實(shí)現(xiàn)了(即在最終鏡像中不保留包緩存)與一個(gè)單一標(biāo)志相當(dāng)?shù)臇|西。

一個(gè)附加的回報(bào):把你的應(yīng)用程序放入基于Alpine鏡像的容器,讓你獲得了一堆有用的工具。如果需要,現(xiàn)在你可以吧shell放入容器并在它運(yùn)行時(shí)做點(diǎn)什么。

打包

我們看到Docker如何幫助我們?cè)诟蓛舄?dú)立的環(huán)境里編譯Go代碼;如何使用不同版本的Go工具鏈;以及如何在不同的操作系統(tǒng)和平臺(tái)之間交叉編譯。

我們還看到Go如何幫我們給Docker創(chuàng)建小的,容器依賴鏡像,并且描述了一些靜態(tài)庫(kù)和網(wǎng)絡(luò)依賴相關(guān)的微妙聯(lián)系(沒別的意思)。

除了Go是真的適合Docker項(xiàng)目這個(gè)事實(shí),我們希望展示給你的是,Go和Docker如何相互借鑒并且一起工作得很好!
致謝

這最初是在2016年GopherCon駭客日提出的。

我要感謝所有的校對(duì)材料、提出建議和意見讓它更好的人,包括但不局限于:

Aaron Lehmann
Stephen Day
AJ Bowen

所有的錯(cuò)誤和拼寫錯(cuò)誤都是我自己的;所有的好東西都是他們的!

感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

相關(guān)文章

  • Docker鏡像的創(chuàng)建、存出、載入的方法

    Docker鏡像的創(chuàng)建、存出、載入的方法

    這篇文章主要介紹了Docker鏡像的創(chuàng)建、存出、載入的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • 一文教會(huì)你用Docker打包Python運(yùn)行環(huán)境

    一文教會(huì)你用Docker打包Python運(yùn)行環(huán)境

    Docker提供了容器級(jí)別的資源隔離,由于Python的外部依賴管理中存在的問(wèn)題,我們通常會(huì)使用virtualenv來(lái)對(duì)不同的項(xiàng)目創(chuàng)建其唯一的依賴環(huán)境,下面這篇文章主要給大家介紹了如何通過(guò)一篇文章教會(huì)你用Docker打包Python運(yùn)行環(huán)境的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • docker部署apollo詳細(xì)教程

    docker部署apollo詳細(xì)教程

    這篇文章主要介紹了docker部署apollo詳細(xì)教程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Docker 查詢、停止、刪除和重啟容器的詳細(xì)過(guò)程

    Docker 查詢、停止、刪除和重啟容器的詳細(xì)過(guò)程

    這篇文章主要介紹了Docker 查詢、停止、刪除和重啟容器,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • Docker容器日志查看和清理的圖文教程

    Docker容器日志查看和清理的圖文教程

    docker容器在運(yùn)行過(guò)程中會(huì)產(chǎn)生日志,日志的量跟具體的容器有關(guān),下面這篇文章主要給大家介紹了關(guān)于Docker容器日志查看和清理的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • 清理或刪除docker無(wú)用鏡像的操作方法

    清理或刪除docker無(wú)用鏡像的操作方法

    這篇文章主要介紹了清理或刪除docker無(wú)用鏡像的操作方法,清除docker無(wú)用鏡像首先查看docker占用的資源,只刪除那些未被使用的資源,文中給大家補(bǔ)充介紹了docker?批量刪除無(wú)用的容器或鏡像的方法,感興趣的朋友一起看看吧
    2023-01-01
  • 聊聊docker中容器與鏡像的區(qū)別

    聊聊docker中容器與鏡像的區(qū)別

    今天什么內(nèi)容不講只給大家講解docker中容器與鏡像的區(qū)別,對(duì)于初學(xué)者來(lái)說(shuō),剛剛接觸docker會(huì)有點(diǎn)迷,特別是鏡像與容器。其實(shí)我們可以理解鏡像與容器為一對(duì)多的關(guān)系。本文給大家介紹的很詳細(xì),感興趣的朋友一起看看吧
    2021-06-06
  • docker-compose部署nacos 2.2.3的詳細(xì)過(guò)程

    docker-compose部署nacos 2.2.3的詳細(xì)過(guò)程

    這篇文章主要介紹了docker-compose部署nacos 2.2.3的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-11-11
  • IDEA 集成 docker 實(shí)現(xiàn)遠(yuǎn)程部署的詳細(xì)步驟

    IDEA 集成 docker 實(shí)現(xiàn)遠(yuǎn)程部署的詳細(xì)步驟

    使用命令 vim /usr/lib/systemd/system/docker.service登錄docker所在的遠(yuǎn)程服務(wù)器,本文重點(diǎn)給大家介紹IDEA 集成 docker 實(shí)現(xiàn)遠(yuǎn)程部署的詳細(xì)步驟,需要的朋友參考下吧
    2021-07-07
  • docker安裝MinIO全過(guò)程

    docker安裝MinIO全過(guò)程

    這篇文章主要介紹了docker安裝MinIO全過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09

最新評(píng)論