网上搜索的大都是(我看到的全都是)把golang项目的源码包全部copy进容器内,然后在容器内RUN go build,这种方案显然不如只COPY 二进制文件到容器内的方案。

一、交叉编译

golang支持交叉编译,在一个平台上生成另一个平台的可执行文件。

Mac下编译linux和windows平台:

     CGO_ENABLE=0 GOOS=linux GOARCH=amd64 go build main.go
     CGO_ENABLE=0 GOOS=windows GOARCH=amd64 go build  main.go

Linux下编译Mac和windows平台:

     CGO_ENABLE=0 GOOS=darwin GOARCH=amd64 go build  main.go
     CGO_ENABLE=0 GOOS=windows GOARCH=amd64 go build  main.go

Windows下编译Mac和Linux平台:

     SET CGO_ENABLE=0
     SET GOOS=darwin
     SET GOARCH=amd64
     go build main.go

     SET CGO_ENABLE=0
     SET GOOS=linux
     SET GOARCH=amd64
     go build main.go

二、实例

  1. 目录结构

main.go

package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run("0.0.0.0:8080") // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

build.sh (这里的交叉编译参数是关键,我的宿主机是Mac,如果不加交叉编译参数,那么生成的二进制文件copy 进入容器也无法正常运行)

#!/bin/sh

CGO_ENABLE=0 GOOS=linux GOARCH=amd64 go build -o gin_docker main.go

docker build -t gin_docker .

Dockerfile 这里只需要把编译的结果gin_docker copy进去即可。这里有一点疑问是,如果已经是可执行文件,那么是否还需要golang:alpine的基础镜像了?大佬们指点下

FROM golang:alpine

WORKDIR /gin_docker

COPY gin_docker ./gin_docker

EXPOSE 8080

ENTRYPOINT  ["./gin_docker"]

start.sh

#!bin/bash

sh build.sh

docker run -p 8080:8080 -d gin_docker

每次修改万代码,要启动只需要执行

sh start.sh

即可。

当然,这里只是镜像的构建,后续将构建的镜像推导镜像仓库,k8s 自动部署对应的镜像就是后续流程了。