11

基于Docker的Golang交叉编译

 3 years ago
source link: https://studygolang.com/articles/28831
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

首先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 protected]>

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 protected]>
    WORKDIR /app
    COPY . .
    RUN chmod 777 main
    # master process
    ENTRYPOINT ["./main"]  
复制代码

第二种是采用 go run 的形式直接运行你的go文件,开启应用进程,同样是基于 gobuilder 镜像,启动时只要挂载项目并修改 ENTRYPOINTCMD 参数即可,具体参考如下命令:

# 如果需要容器应用后台运行,只需将-it改成-d即可
~$ docker run --name YourAppName -it -v /abspath/gosrc/:/go/src/app --entrypoint go gobuilder run main.go
复制代码

总结

本文主要介绍了一种基于 Docker 编译并运行应用的方法,该方法可以在任何( Linux , macOSWindows )安装有 Docker 环境的机器上做到一致性部署。能达到一次编译,到处运行的效果,这一点倒是很像 JAVA 的虚拟机,有异曲同工之妙。通过拉取镜像并实例化容器的方式,同时也能避免每次在新机器上搭建运行时环境的苦恼。本人小白一枚,还在不断学习中,因此若有错误和疏漏的地方,还望指正,谢谢!

欢迎关注我们的微信公众号,每天学习Go知识

FveQFjN.jpg!web

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK