簡(jiǎn)介
很多時(shí)候我們本地開(kāi)發(fā)環(huán)境和線上環(huán)境是不一致的,比如mac開(kāi)發(fā),linux運(yùn)行。通常的做法如下:
本地開(kāi)發(fā)->上傳git->服務(wù)器拉取代碼->編譯->運(yùn)行
時(shí)間久了會(huì)發(fā)現(xiàn),這樣非常麻煩。
一種更好的方式是使用docker構(gòu)建本地編譯環(huán)境,可以非常方便的編譯適合各個(gè)平臺(tái)的程序版本
原理
原理很簡(jiǎn)單,就是利用官方提供的golang鏡像,將本地的代碼通過(guò)掛載的方式,掛載到容器中,然后再容器中編譯即可。
golang開(kāi)發(fā)環(huán)境的鏡像我們這里選擇golang:1.8(也可以選擇其他的鏡像),這個(gè)鏡像的目錄結(jié)構(gòu)為:
/go/bin
/go/src
他的gopath 為 /go
可以通過(guò)以下命令查看:
docker run --rm golang:1.8 go env
具體可以參考官方dockerfile文件,搜索gopath即可。
https://github.com/docker-library/golang/blob/9bf6daddb324a4d8e82b0613cf348a6eff363f95/1.10/stretch/Dockerfile
因此,我們可以將本地的gopath映射到容器的/go目錄(這樣我們項(xiàng)目依賴的go包也會(huì)自動(dòng)掛載到容器的gopath目錄下)
將要編譯的本地程序映射到容器的/go/src/myapp 目錄下,然后執(zhí)行編譯即可。
舉例
一條命令就可以搞定:
docker run -v "$GOPATH":/go --rm -v "$PWD":/go/src/myapp -w /go/src/myapp -e GOOS="darwin" -e GOARCH="amd64" golang:1.8 go build -v
解釋下這句話的意思:
--rm :會(huì)在每次執(zhí)行完編譯后自動(dòng)刪除容器(不加這個(gè)參數(shù),使用docker ps -a會(huì)看到我們上一次執(zhí)行結(jié)束的容器)
-v "$GOPATH":/go:將本地gopath映射到容器中,這樣容器中就不會(huì)提示缺少包
-v "$PWD":/go/src/myapp:將本地代碼映射到容器中,本地代碼目錄為myapp
-e GOOS/-e GOARCH:指定編譯平臺(tái),可以很方便的進(jìn)行交叉編譯
golang:1.8:鏡像名稱
這樣,我們只需要在我們的代碼目錄下,增加一個(gè)腳本build.sh, 內(nèi)容如下:
docker run -v "$GOPATH":/go --rm -v "$PWD":/go/src/myapp -w /go/src/myapp -e GOOS="darwin" -e GOARCH="amd64" golang:1.8 go build -v
可以根據(jù)需求,自己修改這個(gè)腳本。
然后再需要編譯的時(shí)候,直接執(zhí)行這個(gè)腳本就會(huì)在本地目錄下生成編譯好的二進(jìn)制文件,非常方便
疑問(wèn)
golang對(duì)交叉編譯支持的很好,最簡(jiǎn)單的方式如下:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
不過(guò)對(duì)于某些項(xiàng)目,直接本地交叉編譯經(jīng)常報(bào)錯(cuò),報(bào)錯(cuò)原因沒(méi)有深究。還是采用本文所述方法,保持程序運(yùn)行環(huán)境和編譯環(huán)境一致最穩(wěn)妥。
歡迎加入我的知識(shí)星球,一起討論技術(shù)。Coding A Better Life!
