首先Go自己在交叉编译方法十分强大,这里就再也不赘述了,有须要的同窗能够参考《Golang交叉编译各个平台的二进制文件》。虽然自带的交叉编译已足够强大,而且能知足大部分的使用场景,但仍是有一个坑人的地方就是当源代码中包含CGO代码时,默认交叉编译就会出错,具体能够参考《CGO_ENABLED环境变量对Go静态编译机制的影响》。实际上有一种能够一劳永逸地解决,并保证线下编译与线上部署环境一致的项目构建方法,那就是基于Docker的“交叉编译方案”。html
Docker是近年来十分流行的Linux容器化技术,相比传统的虚拟机技术,其占用的系统资源更小,体积小,启动速度也很是迅捷。同时Docker已经能在主流操做系统Windows, macOS和Linux上获得快速的构建,这一点对本文接下来要讲的交叉编译十分重要。有关容器的详细介绍具体可参考docker入门教程,其安装方法也很是简单。git
为了保证一次编译,处处运行的效果(有点相似JAVA虚拟机),所以须要采用同一个Docker基础镜像分别用于代码编译和部署的工做,本文基于DockerHub官方发布的golang:1.14.3-stretch定制了一个镜像,该镜像更加方便对项目代码的编译导出,镜像体积大概在280MB左右,比较能使人接受。下面是镜像的Dockerfile:golang
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
docker
有了上面的Dockerfile
,而后咱们就能迅速地构建镜像并实例化相应的容器,从而完成对项目源代码的编译和部署工做,具体步骤以下:vim
# 在Dockerfile所处当前目录下,执行
~$ docker build -t gobuilder:1.14.3-stretch .
复制代码
# 假设你的项目目录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
复制代码
在这里,直接运行go项目有两种方法:
第一种是像刚才介绍的那样,先编译后执行导出的可执行文件就可运行你的应用。若是是线上部署,一样能够在镜像gobuilder
能够专门给你的main
可执行文件编写特定的Dockerfile
用于应用镜像的构建和实例化,具体能够参考如下的构建方法:app
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
参数便可,具体参考以下命令:curl
# 若是须要容器应用后台运行,只需将-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
的虚拟机,有殊途同归之妙。经过拉取镜像并实例化容器的方式,同时也能避免每次在新机器上搭建运行时环境的苦恼。本人小白一枚,还在不断学习中,所以如有错误和疏漏的地方,还望指正,谢谢!学习