Golang之 在Docker Image中编译方式

Posted by 董江 on Sunday, August 7, 2022

由于开发调试编译需要,需要编译amd64aarch64arm64等不同平台指令二进制;或者,不希望编译机器安装太多依赖多版本依赖版本不兼容等, 使用容器内编译非常方便.

容器编译几种方式

方式一: 通过Docker multi-stage build机制

golang简单demo为例:

package main

import (
	"net/http"
	"time"

	"github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {
	mux := http.NewServeMux()

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("this is demo!"))
	})

	mux.Handle("/metrics", promhttp.Handler())

	s := &http.Server{
		Addr:           ":8080",
		Handler:        mux,
		ReadTimeout:    time.Second * 5,
		WriteTimeout:   time.Second * 5,
		MaxHeaderBytes: 1 << 20, // 1048576; 1MiB
	}
	s.ListenAndServe()
}
# Builder
FROM golang:1.18.5-alpine as builder

RUN mkdir -p src/github.com/dongjiang1989/

WORKDIR ./src/github.com/dongjiang1989/

COPY . ./server

WORKDIR ./server

RUN export GOPATH=/go/src

RUN export GO111MODULE=off

RUN cd server && go build -ldflags "-linkmode external -extldflags -static" -o /demo-server ./main.go

# Server
FROM alpine

EXPOSE 8080

COPY --from=builder /demo-server /demo-server

ENTRYPOINT ["/demo-server"]

通过COPY copy代码目录到 Docker image中,进行编译。

  • 好处: Dockerfile可以在任何地方执行
  • 缺点:中间产物不出现本地目录

方式二: 通过docker run 挂载本地卷,执行 sh指令

docker run -it --rm -v `pwd`/server:/go/src/github.com/dongjiang1989/server golang:1.18.5-alpine sh -c "apk add --no-cache gcc musl-dev libc6-compat && \
cd /go/src/github.com/dongjiang1989/server && \
GOPATH=/go  GO111MODULE=off go build -ldflags '-linkmode external -extldflags -static' -o demo-server ./main.go" 

结果在本地

dongjiangdeMacBook-Pro:dongjiang1989 $ docker run -it --rm -v `pwd`/server:/go/src/github.com/dongjiang1989/server golang:1.18.5-alpine sh -c "apk add --no-cache gcc musl-dev libc6-compat && \
cd /go/src/github.com/dongjiang1989/server && \
GOPATH=/go  GO111MODULE=off go build -ldflags '-linkmode external -extldflags -static' -o demo-server ./main.go"
fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/community/x86_64/APKINDEX.tar.gz
(1/12) Installing libgcc (11.2.1_git20220219-r2)
(2/12) Installing libstdc++ (11.2.1_git20220219-r2)
(3/12) Installing binutils (2.38-r3)
(4/12) Installing libgomp (11.2.1_git20220219-r2)
(5/12) Installing libatomic (11.2.1_git20220219-r2)
(6/12) Installing gmp (6.2.1-r2)
(7/12) Installing isl22 (0.22-r0)
(8/12) Installing mpfr4 (4.1.0-r0)
(9/12) Installing mpc1 (1.2.1-r0)
(10/12) Installing gcc (11.2.1_git20220219-r2)
(11/12) Installing libc6-compat (1.2.3-r0)
(12/12) Installing musl-dev (1.2.3-r0)
Executing busybox-1.35.0-r15.trigger
OK: 119 MiB in 27 packages
dongjiangdeMacBook-Pro:dongjiang1989 $ cd server 
dongjiangdeMacBook-Pro:server $ ls
demo-server dokcerfile  go.mod      go.sum      main.go     vendor

通过docker run, 并挂载local volume添加代码,更改指令集编译服务

  • 好处:不需要dockerfile, 可以在前人肩膀上(现有docker images)执行;中间产物在本地volume中
  • 缺点:shell命令拼接问题,建议写本地Makefile

「如果这篇文章对你有用,请随意打赏」

Kubeservice博客

如果这篇文章对你有用,请随意打赏

使用微信扫描二维码完成支付