使用 Docker Multi-Stage 编译 Go 程序最佳姿势

DevOps技术栈

共 2178字,需浏览 5分钟

 · 2020-08-10

作者:AppleBoy

链接:http://suo.im/5KL8v2

本文通过 Go 语言的 Hello World 來介绍基于 Docker 的 Single build 及 Multiple build。

Single build

下面是 Go 语言 Hello World 代码:

package main

import "fmt"

func main() {
    fmt.Println("Hello World!")
}

接着用 alpine 的 Go 语言 Image 来编译出可执行文件。

FROM golang:alpine
WORKDIR /app
ADD . /app
RUN cd /app && go build -o app
ENTRYPOINT ./app

接着执行如下编译指令:

$ docker build -t appleboy/go-app .
$ docker run --rm appleboy/go-app

最后检查看看编译出来的 Image 大小,使用docker images | grep go-app,会发现大小为 258 MB

Multiple build

Multiple build 则是可以在Dockerfile使用多个不同的 Image 来源,请看看底下例子:

# build stage
FROM golang:alpine AS build-env
ADD . /src
RUN cd /src && go build -o app

# final stage
FROM alpine
WORKDIR /app
COPY --from=build-env /src/app /app/
ENTRYPOINT ./app

从上面可以看到透过AS--from互相沟通,以前需要写两个 Dockerfile,现在只要一个就可以搞定。

$ docker build -t appleboy/go-app .
$ docker run --rm appleboy/go-app

会发现最后大小为 6.35 MB,比上面是不是小了很多。

最小 Image

6.35 MB 是最小的 Image 了吗?一个简单的 Hello World 可执行文件,用 Docker 包起来竟然要 6.35,其实不用这么大,我们可以透过 Dokcer 所提供的最小 Image:scratch,将二进制文件直接扔进去即可,在编译可执行文件时需加入特定参数才可以:

$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app

在通过 Docker 包起来:

FROM centurylink/ca-certs

ADD app /

ENTRYPOINT ["/app"]

编译出来大小为:1.81MB,相信这是最小的 Image 了。

注:centurylink/ca-certs 是一个基于 Docker 的基础镜像,它基于 scratch 镜像构建,并为所有标准证书颁发机构添加了根证书。

完整的 Dockerfile:

# build stage
FROM golang:alpine AS build-env
ADD . /src
RUN cd /src && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app

# final stage
FROM centurylink/ca-certs
COPY --from=build-env /src/app /
ENTRYPOINT ["/app"]

总结

Multiple build 非常方便,这样就可以将多个步骤全部合并在一个 Dockerfile 处理掉,像是底下例子:

from debian as build-essential
arg APT_MIRROR
run apt-get update
run apt-get install -y make gcc
workdir /src

from build-essential as foo
copy src1 .
run make

from build-essential as bar
copy src2 .
run make

from alpine
copy --from=foo bin1 .
copy --from=bar bin2 .
cmd ...

用一个 Dockerfile 产生多个可执行文件,最后再用 alpine 打包成 Image。

- END -

精彩文章推荐:

从网管到架构师再到微创业,我这9年的成长感悟

12年老司机总结的 5 条面试忠告,终身受用

一篇漫画带你了解 Linux 内核长啥样!

SSH只能用于远程Linux主机?那说明你见识太小了!

10 个Linux Awk文本处理经典案例

Linux 系统故障排查,看这一篇就够了

10 分钟部署一个 Kubernetes 集群

部署一套完整的Kubernetes高可用集群(二进制)




点亮,服务器三年不宕机

浏览 7
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报