亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 服務器 > Web服務器 > 正文

Docker與Golang的巧妙結合

2024-09-01 13:48:41
字體:
來源:轉載
供稿:網友

Docker與Golang的巧妙結合

【編者的話】這是一個展示在使用Go語言時如何讓Docker更有用的提示與技巧的簡輯。例如,如何使用不同版本的Go工具鏈來編譯Go代碼,如何交叉編譯到不同的平臺(并且測試結果?。蛘呷绾沃谱髡嬲〉娜萜麋R像。

下面的文章假定你已經安裝了Docker。不必是最新版本(這篇文章不會使用Docker任何花哨的功能)。
沒有go的Go

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

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

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

如果遇到上述情況,找Docker來解決!

在容器里編譯一個程序

當你安裝了Go,你可以執行go get -v github.com/user/repo來下載,創建和安裝一個庫。(-v只是信息顯示,如果你喜歡工具鏈快速和靜默地運行,可以將它移除!)

你也可以執行go get github.com/user/repo/...來下載,創建和安裝那個repo(包括庫和二進制文件)里面所有的東西。

我們可以在一個容器里面這樣做!

試試這個:

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

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

在容器里運行程序

一個辦法是提交我們剛剛創建的容器,即,打包它到一個新的鏡像:

docker commit $(docker ps -lq) awesomeness

注意:docker ps –lq輸出最后一個執行的容器的ID(只有ID?。H绻闶菣C器的唯一用戶,并且你從上一個命令開始沒有創建另一個容器,那這個容器就是你剛剛創建的“hello world”的例子。

現在,可以用剛剛構建的鏡像創建容器來運行程序:

docker run awesomeness hello

輸出會是Hello, Go examples!。

閃光點

當用docker commit構建鏡像時,可以用--change標識指定任意Dockerfile命令。例如,可以使用一個CMD或者ENTRYPOINT命令以便docker run awesomeness自動執行hello。

在一次性容器上運行

如果不想創建額外的鏡像只想運行這個Go程序呢?

使用:

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

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

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

使用不同版本的Go

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

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

例如,想用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鏡像頁面上看到所有可用的版本(和變量)。

在系統上安裝

好了,如果想在系統上運行編譯好的程序,而不是一個容器呢?我們將復制這個編譯了的二進制文件到容器外面。注意,僅當容器架構和主機架構匹配的時候,才會起作用;換言之,如果在Linux上運行Docker。(我排除的可能是運行Windows容器的人?。?/p>

最容易在容器外獲得二進制文件的方法是映射$GOPATH/bin目錄到一個本地目錄,在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上,可能會看到:
-bash:

/tmp/test/hello: cannot execute binary file

我們又能做什么呢?

交叉編譯

Go 1.5具備優秀的開箱即用交叉編譯能力,所以如果你的容器操作系統和/或架構和你的系統不匹配,根本不是問題!

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

例如,假設在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.。換言之,想運行程序,得執行/tmp/crosstest/darwin_amd64/hello.。

直接安裝到$PATH

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

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

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

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

創建依賴鏡像

我們用這種技術產生的Go二進制文件是靜態鏈接的。這意味著所有需要運行的代碼包括所有依賴都被嵌入了。動態鏈接的程序與之相反,不包含一些基本的庫(像“libc”)并且使用系統范圍的復制,是在運行時確定的。

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

我們試試!

scratch鏡像

Docker生態系統有一個特殊的鏡像:scratch.這是一個空鏡像。它不需要被創建或者下載,因為定義的就是空的。

給新的Go依賴鏡像創建一個新的空目錄。

在這個新目錄,創建下面的Dockerfile:

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

這意味著:從scratch開始(一個空鏡像),增加hello文件到鏡像的根目錄,*定義hello程序為啟動這個容器后默認運行的程序。

然后,產生hello二進制文件如下:

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

注意:不需要設置GOOS和GOARCH,正因為,想要一個運行在Docker容器里的二進制文件,不是在主機上。所以不用設置這些變量!

然后,創建鏡像:

docker build -t hello .

測試它:

docker run hello

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

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

如果一切做得正確,這個鏡像大約2M。相當好!
構建東西而不推送到Github

當然,如果不得不推送到GitHub,每次編譯都會浪費很多時間。

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

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

# Adapt the two following environment variables if you are not running on a Macexport GOOS=darwin GOARCH=amd64mkdir go-and-docker-is-lovecd go-and-docker-is-lovegit clone git://github.com/golang/examplecat example/hello/hello.gosed -i .bak s/olleH/eyB/ example/hello/hello.godocker 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!" 

網絡包和CGo的特殊情況

進入真實的Go代碼世界前,必須承認的是:在二進制文件上有一點點偏差。如果在使用CGo,或如果在使用net包,Go鏈接器將生成一個動態庫。這種情況下,net包(里面確實有許多有用的Go程序!),罪魁禍首是DNS解析。大多數系統都有一個花哨的,模塊化的名稱解析系統(像名稱服務切換),它依賴于插件,技術上,是動態庫。默認地,Go將嘗試使用它;這樣,它將產生動態庫。

我們怎么解決?

重用另一個版本的libc

一個解決方法是用一個基礎鏡像,有那些程序功能所必需的庫。幾乎任何“正規”基于GNU libc的Linux發行版都能做到。所以,例如,使用FROM debian或FROM fedora,替代FROM scratch?,F在結果鏡像會比原來大一些;但至少,大出來的這一點將和系統里其它鏡像共享。

注意:這種情況不能使用Alpine,因為Alpine是使用musl庫而不是GNU libc。

使用自己的libc

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

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

用netgo生成靜態二進制文件

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

要使用它,只需在go get選項加入-tags netgo -installsuffix netgo。

-tags netgo指示工具鏈使用netgo。

-installsuffix netgo確保結果庫(任何)被一個不同的,非默認的目錄所替代。如果做多重go get(或go build)調用,這將避免

代碼創建和用不用netgo之間的沖突。如果像目前我們講到的這樣,在容器里創建,是完全沒有必要的。因為這個容器里面永遠沒有其他Go代碼要編譯。但它是個好主意,習慣它,或至少知道這個標識存在。

SSL證書的特殊情況

還有一件事,你會擔心,你的代碼必須驗證SSL證書;例如,通過HTTPS聯接外部API。這種情況,需要將根證書也放入容器里,因為Go不會捆綁它們到二進制文件里。
安裝SSL證書

再次,有很多可用的選擇,但最簡單的是使用一個已經存在的發布里面的包。

Alpine是一個好的選擇,因為它非常小。下面的Dockerfile將給你一個小的基礎鏡像,但捆綁了一個過期的跟證書:

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

來看看吧,結果鏡像只有6MB!

注意:--no-cache選項告訴apk(Alpine包管理器)從Alpine的鏡像發布上獲取可用包的列表,不保存在磁盤上。你可能會看到Dockerfiles做這樣的事apt-get update && apt-get install ... && rm -rf /var/cache/apt/*;這實現了(即在最終鏡像中不保留包緩存)與一個單一標志相當的東西。

一個附加的回報:把你的應用程序放入基于Alpine鏡像的容器,讓你獲得了一堆有用的工具。如果需要,現在你可以吧shell放入容器并在它運行時做點什么。

打包

我們看到Docker如何幫助我們在干凈獨立的環境里編譯Go代碼;如何使用不同版本的Go工具鏈;以及如何在不同的操作系統和平臺之間交叉編譯。

我們還看到Go如何幫我們給Docker創建小的,容器依賴鏡像,并且描述了一些靜態庫和網絡依賴相關的微妙聯系(沒別的意思)。

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

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

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

Aaron Lehmann
Stephen Day
AJ Bowen

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

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


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美性受xxxx黑人猛交| 在线成人中文字幕| 狠狠干狠狠久久| 成人中文字幕在线观看| 亚洲福利视频二区| 国产在线视频欧美| 亚洲福利在线观看| 亚洲**2019国产| 亚洲精品第一页| 欧美精品在线免费观看| 高清在线视频日韩欧美| 国产精品久久久久av免费| 成人性生交大片免费观看嘿嘿视频| 欧美一区二区三区免费视| 欧美乱大交xxxxx另类电影| 国语自产精品视频在线看| 亚洲精品免费av| 亚洲va男人天堂| 日韩av色综合| 国内精品免费午夜毛片| 久久天堂电影网| 精品视频在线导航| 26uuu国产精品视频| 性色av一区二区三区免费| 欧美丝袜第一区| 亚洲欧美日韩综合| 亚洲精品videossex少妇| 欧美国产日韩一区二区三区| 亚洲欧美激情另类校园| 91在线观看免费高清| 国产主播在线一区| 欧美视频免费在线| 成人性教育视频在线观看| 久久久久久尹人网香蕉| 欧美一级淫片丝袜脚交| 91精品视频在线| 国产精品狼人色视频一区| 日韩欧美亚洲国产一区| 久久久久久久久久久网站| 久久久久久久久久久人体| 亚洲日韩欧美视频| 欧美猛男性生活免费| 92国产精品视频| 国产精品久久不能| 爽爽爽爽爽爽爽成人免费观看| 亚洲成av人影院在线观看| 97在线视频免费看| 国产日韩欧美日韩大片| 欧美视频在线免费看| 日韩专区在线播放| 一区二区欧美亚洲| 最近2019中文字幕第三页视频| 日韩欧美一区二区在线| 欧美激情一区二区三级高清视频| 欧美激情亚洲一区| 欧美黑人又粗大| 国产精品福利久久久| 成人黄色片网站| 国产精品av电影| 国产亚洲精品激情久久| 95av在线视频| 欧美日韩国产限制| 日韩av在线资源| 亚洲最大激情中文字幕| 美女啪啪无遮挡免费久久网站| 亚洲女人被黑人巨大进入| 欧美在线一区二区视频| 成人免费网站在线观看| 国产一区二区黑人欧美xxxx| 中文字幕精品影院| 亚洲无限乱码一二三四麻| 亚洲在线免费看| 久久成人av网站| 日韩精品在线视频观看| 国产丝袜精品视频| 久久久国产精品x99av| 26uuu久久噜噜噜噜| 日韩美女激情视频| 中文字幕亚洲无线码在线一区| 国产一区二区精品丝袜| 久久久97精品| 精品丝袜一区二区三区| 亚洲视频专区在线| 久久久久免费精品国产| 在线播放精品一区二区三区| 日韩欧美精品免费在线| 成人福利免费观看| 91高清免费视频| 日韩成人激情视频| 国产精品入口福利| 亚洲国产精品高清久久久| 国产精品99久久久久久www| 亚洲亚裔videos黑人hd| 国产成人av在线播放| 国产精品91久久久| 国产精品流白浆视频| 国产成人精品国内自产拍免费看| 欧美影院成年免费版| 久久精品99久久香蕉国产色戒| 久久91超碰青草是什么| 国产精品va在线播放| 久久婷婷国产麻豆91天堂| 国产精品亚洲综合天堂夜夜| 亚洲人成电影在线观看天堂色| 亚洲四色影视在线观看| 亚洲精品一区二区在线| 一区二区三区视频免费在线观看| 久久国产精品久久久久久| 欧美日韩中文字幕在线视频| 国模精品系列视频| 国产成人一区二区三区小说| 中文字幕国产精品| 亚洲精品v天堂中文字幕| 欧美激情小视频| 欧美一级淫片播放口| 精品欧美一区二区三区| 欧美性生交xxxxx久久久| 亚洲国产欧美一区二区三区同亚洲| 国产精品久久久久久久久久新婚| 在线观看欧美视频| 色777狠狠综合秋免鲁丝| 日韩精品小视频| 97视频在线观看网址| 亚洲国产成人精品一区二区| 国产精品美女无圣光视频| 狠狠色香婷婷久久亚洲精品| 91精品国产综合久久久久久久久| 日韩在线观看av| 永久免费精品影视网站| 久久久精品一区二区三区| 久久免费在线观看| 国产欧美精品日韩| 中文字幕一精品亚洲无线一区| 亚洲国产天堂久久国产91| 亚洲国产精品久久久久| 亚洲老头同性xxxxx| 欧美激情乱人伦| 亚洲aⅴ男人的天堂在线观看| 午夜精品久久久久久久男人的天堂| 91最新国产视频| 成人国内精品久久久久一区| 国产精品aaaa| 亚洲成人网在线| 精品视频在线播放色网色视频| 欧美另类在线观看| 国产精品88a∨| 欧美亚洲另类制服自拍| 成人激情av在线| 欧美另类在线观看| 欧美网站在线观看| 国产啪精品视频网站| 欧美高清视频一区二区| 欧美日韩国产色| 91免费国产网站| 亚洲男人天堂2023| 日本久久久久久久久| 91久久精品国产91久久| 最新国产精品拍自在线播放| 国产精品亚洲网站| 欧美人与性动交| 色婷婷综合久久久久| 亚洲天堂开心观看| 国产91精品高潮白浆喷水| 亚洲福利在线看|