基於Docker的Golang交叉編譯
前言
首先Go本身在交叉編譯方法十分強大,這里就不再贅述了,有需要的同學可以參考《Golang交叉編譯各個平台的二進制文件》。雖然自帶的交叉編譯已足夠強大,並且能滿足大部分的使用場景,但還是有一個坑人的地方就是當源代碼中包含CGO代碼時,默認交叉編譯就會出錯,具體可以參考《CGO_ENABLED環境變量對Go靜態編譯機制的影響》。實際上有一種可以一勞永逸地解決,並保證線下編譯與線上部署環境一致的項目構建方法,那就是基於Docker的“交叉編譯方案”。
Docker是近年來十分流行的Linux容器化技術,相比傳統的虛擬機技術,其占用的系統資源更小,體積小,啟動速度也非常迅捷。同時Docker已經能在主流操作系統Windows, macOS和Linux上得到快速的構建,這一點對本文接下來要講的交叉編譯十分重要。有關容器的詳細介紹具體可參考docker入門教程,其安裝方法也非常簡單。
方法
准備一個基礎鏡像
為了保證一次編譯,到處運行的效果(有點類似JAVA虛擬機),因此需要采用同一個Docker基礎鏡像分別用於代碼編譯和部署的工作,本文基於DockerHub官方發布的golang:1.14.3-stretch定制了一個鏡像,該鏡像更加方便對項目代碼的編譯導出,鏡像體積大概在280MB左右,比較能令人接受。下面是鏡像的Dockerfile:
FROM golang:1.14.3-stretch
MAINTAINER author <email@xxx.com>
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
wget \
vim \
htop \
curl \
sudo \
git \
net-tools \
tzdata \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& rm -rf /var/lib/apt/lists/*
ENV GOBIN=$GOPATH/bin
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.io,direct
ENV TZ=Asia/Shanghai
WORKDIR $GOPATH/src/app
ENTRYPOINT ["go", "build"]
復制代碼
p.s. 以上鏡像的Golang環境默認開啟GOMODULE模式,因此為保證能順利編譯,項目需要初始化go.mod
如何使用
有了上面的Dockerfile
,然后我們就能迅速地構建鏡像並實例化相應的容器,從而完成對項目源代碼的編譯和部署工作,具體步驟如下:
1. 構建鏡像
# 在Dockerfile所處當前目錄下,執行
~$ docker build -t gobuilder:1.14.3-stretch .
復制代碼
2. 編譯你的項目go源碼
# 假設你的項目目錄gosrc包含以下文件:
/abspath/gosrc
|---package
| |---func1.go
| |---func2.go
|---go.mod
|---config.yml
|---main.go
# 運行以下容器編譯你的go項目並導出可執行文件到當前目錄下
~$ docker run --rm -it -v /abspath/gosrc/:/go/src/app gobuilder
復制代碼
3. 運行你的go項目
在這里,直接運行go項目有兩種方法:
第一種是像剛才介紹的那樣,先編譯后執行導出的可執行文件就可運行你的應用。如果是線上部署,同樣可以在鏡像gobuilder
可以專門給你的main
可執行文件編寫特定的Dockerfile
用於應用鏡像的構建和實例化,具體可以參考以下的構建方法:
FROM gobuilder:1.14.3-stretch
MAINTAINER author <email@xxx.com>
WORKDIR /app
COPY . .
RUN chmod 777 main
# master process
ENTRYPOINT ["./main"]
復制代碼
第二種是采用go run
的形式直接運行你的go文件,開啟應用進程,同樣是基於gobuilder
鏡像,啟動時只要掛載項目並修改ENTRYPOINT
和CMD
參數即可,具體參考如下命令:
# 如果需要容器應用后台運行,只需將-it改成-d即可
~$ docker run --name YourAppName -it -v /abspath/gosrc/:/go/src/app --entrypoint go gobuilder run main.go
復制代碼
總結
本文主要介紹了一種基於Docker
編譯並運行應用的方法,該方法可以在任何(Linux
, macOS
和Windows
)安裝有Docker
環境的機器上做到一致性部署。能達到一次編譯,到處運行的效果,這一點倒是很像JAVA
的虛擬機,有異曲同工之妙。通過拉取鏡像並實例化容器的方式,同時也能避免每次在新機器上搭建運行時環境的苦惱。本人小白一枚,還在不斷學習中,因此若有錯誤和疏漏的地方,還望指正,謝謝!