Golang的docker嘗試 頂 原 薦

一、 前言

docker 就不在這裏介紹了,相關的文檔已經很完善,中文文檔 Docker —— 從入門到實踐 寫的很棒,推薦去看看。

docker 基於 Golang 開發,已經不用解釋了,而 Golang 天生適合運行在 docker 容器中,卻不是這個原因,這得益於:Golang 的靜態編譯,當在編譯的時候關閉 cgo 的時候,可以完全不依賴系統環境。

二、 Golang代碼

我們打算在 docker 中測試 Golang ,所以先編寫一個 Golang 的測試代碼。

新建文件:vi main.go

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

func main() {
	resp, err := http.Get("https://www.baidu.com")
	check(err)
	body, err := ioutil.ReadAll(resp.Body)
	check(err)
	fmt.Println(len(body))
}

func check(err error) {
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

這是一個簡單的程序,拉取百度的頁面,並計算頁面的字節大小。

需要注意的時,這裏採用了 https ,這裏埋下一個伏筆,後面解釋。

三、 編寫 dockerfile

1. 基於完整鏡像

Docker官方提供了Golang各版本的鏡像: Official Repository - golang.

新建文件:vi dockerfile

FROM golang:latest
RUN mkdir /app 
ADD . /app/ 
WORKDIR /app 
RUN go build -o main . 
CMD ["/app/main"]

Docker的鏡像必須基於某個鏡像開始,然後開始創建新的鏡像,這裏基於 golang:latest 開始創建,在鏡像裏創建/app文件夾,並將當前所在文件夾內所有內容添加到鏡像內的/app文件內,將鏡像內的/app設置爲容器工作目錄(這裏不可使用RUN cd /app切換當前工作目錄); 然後編譯當前目錄下Golang代碼,然後使用CMD命令運行剛纔編譯出的程序。

具體命令解釋查看:Dockerfile 指令詳情

1) 當前目錄下文件

admin@dingdayu-DS:/volume1/docker/docker-golang$ ls
dockerfile  main.go

輸入圖片說明

2) 編譯鏡像

sudo docker build -t golang-latest-app .

輸入圖片說明

受制於網絡和機器的性能,編譯鏡像,竟然花了20多分鐘。。。

鏡像編譯完成,完整大小739M,對於線上的部署,無論是編譯時間還是大小都是不合適的,下面的scratch鏡像,用來解決這個問題。

輸入圖片說明

sudo docker run -it --rm --name my-golang-app golang-latest-app

執行鏡像,查看效果:

輸入圖片說明

2. 基於scratch鏡像

scratch 是一個特殊的鏡像,它是一個虛擬鏡像,也就是一個空白鏡像;利用Golang的靜態化編譯無依賴性,可以大幅度減少編譯時間和鏡像大小。

1) 編譯Golang

基於scratch必須先打包,然後才能進行運行。

CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

GOOS=linux 是將交叉編譯的目標設置爲Linux,這樣你在Mac或者Win下也不會出現問題。 cgo 是爲了在靜態編譯中導入net

2) 編輯dockerfile

修改文件:vi dockerfile

FROM scratch
RUN mkdir /app
ADD main /app/
WORKDIR /app
CMD ["/app/main"]

3) 編譯鏡像

sudo docker build -t golang-scratch-app .

輸入圖片說明

scratchgolang:latest的大小差了730多兆。。。。

4) 空白鏡像掛載文件

啓動鏡像

sudo docker run -it --rm --name my-golang-scratch golang-scratch-app

你會發現提示:

Get https://www.baidu.com: x509: failed to load system roots and no roots provided

這是一個非常常見的問題:爲了進行SSL請求,我們需要SSL根證書。

5) 掛載文件

根據操作系統,這些證書可以在許多不同的地方。如果您查看Gox509庫,可以查看Go搜索的所有位置。對於許多Linux發行版,這是/etc/ssl/certs/cacert.pem。首先,我們將把我們的機器(或Linux VM在線證書提供者)的cacert.pem複製到我們的存儲庫中。然後,我們將在Docker文件中添加一個ADD,將這個文件放在Go所期望的位置:

下載 cacert.pem 到當前工作目錄:

wget https://curl.haxx.se/ca/cacert.pem

再次編輯dockerfile

FROM scratch
ADD cacert.pem /etc/ssl/certs/
ADD main /
CMD ["/main"]

6) 執行鏡像

sudo docker run -it --rm --name my-golang-scratch golang-scratch-app

輸入圖片說明

完美執行!

四、 關鍵點

  • Dockerfile 指令詳情
  • 鏡像編譯命令: sudo docker build -t golang-latest-app . => golang-latest-app 爲鏡像名
  • 容器啓動命令: sudo docker run -it --rm --name my-golang-app golang-latest-app => my-golang-app 爲容器名,golang-latest-app 爲鏡像名
  • Golang的靜態編譯: CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

五、 鏈接

  1. Building Minimal Docker Containers for Go Applications
  2. [創建超小的Golang docker 鏡像](http://colobu.com/2015/10/12/create-minimal-golang-docker-images/
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章