![](http://mmbiz.qpic.cn/mmbiz_gif/IP70Vic417DOjMRrV3RrW2HaXlrTFpEI1EYiaJaJkfYOvEuQc3F6RibYXS9oMIvvJNCywron0Wd809g43gmTHlqEA/640?wx_fmt=gif)
go 项目怎么让 docker 镜像体积减小?本文做了详细介绍。
1. 直接编译得到运行文件 22M
使用的项目源码地址 (https://github.com/scoful/kingProject)
本地直接编译打一个linux运行包
set GOOS=linux
set GOARCH=amd64
go build main.go
![](http://mmbiz.qpic.cn/mmbiz_png/ytcTQO90QusibnXbgGNOITOVH9tWHBKPicntCVwF1cibjfXob53ZzRukHo59fcTpjefBu4JkbWKt2Bqx5iap49oPTw/640?wx_fmt=png)
结果是22M
2. 不编译直接运行的镜像 941M
Dockerfile文件内容
FROM golang
MAINTAINER scoful
WORKDIR $GOPATH/kingProject
COPY . $GOPATH/kingProject
ENV GOPROXY https://goproxy.cn,direct
EXPOSE 8888
VOLUME ["/go/kingProject/config","/go/kingProject/log"]
ENTRYPOINT ["go","run","main.go"]
编译镜像后查询结果如下:
![](http://mmbiz.qpic.cn/mmbiz_png/ytcTQO90QusibnXbgGNOITOVH9tWHBKPiclZGXibgRXqiagCpNBLutiaicfibbB1LkUAbYIat73CD6I9jfkHk7mOVyp3Q/640?wx_fmt=png)
结果是941M,基本跟基础镜像golang的大小一致,而且因为没有预先编译,等到运行的时候再编译并拉取依赖包,run起来很慢
3. 编译后的镜像 1.14G
Dockerfile文件内容
FROM golang
MAINTAINER scoful
WORKDIR $GOPATH/kingProject
COPY . $GOPATH/kingProject
ENV GOPROXY https://goproxy.cn,direct
RUN GOOS=linux GOARCH=amd64 go build main.go
EXPOSE 8888
VOLUME
["/go/kingProject/config","/go/kingProject/log"]
ENTRYPOINT ["./main"]
![](http://mmbiz.qpic.cn/mmbiz_png/ytcTQO90QusibnXbgGNOITOVH9tWHBKPicpg8QNqeL0vbm5gBGyKLwpZKuq58eeuGzUbwswjOQ5YkS1YE03h8oKg/640?wx_fmt=png)
结果是1.14G,更大了,因为加上了编译过程中拉取的包,但是预先编译,所以直接run,速度很快
4. 优化:使用alpine版本的基础镜像 517M
优化的方向:如果一个镜像在https://hub.docker.com/里能搜到有alpine版本,尽量用alpine版本,相当于是官方提供的最小化可用版本
Dockerfile文件内容
FROM golang:alpine
MAINTAINER scoful
WORKDIR $GOPATH/kingProject
COPY . $GOPATH/kingProject
ENV GOPROXY https://goproxy.cn,direct
RUN GOOS=linux GOARCH=amd64 go build main.go
EXPOSE 8888
VOLUME ["/go/kingProject/config","/go/kingProject/log"]
ENTRYPOINT ["./main"]
![](http://mmbiz.qpic.cn/mmbiz_png/ytcTQO90QusibnXbgGNOITOVH9tWHBKPicYlHuWk4O5xN1H9xJbaFwacVgB4IicBlYE1gVBEKFNWGtP3RmWKMgM6g/640?wx_fmt=png)
结果是517M,比1.14G减少了650.36M,直接降了56%,而且run一样很快
5. 再优化:使用多级构建的镜像 28.4M
再优化的方向:go项目其实只是在build的阶段需要go环境,run的时候是不需要的,那build完后go环境用个alpine版本就行
Dockerfile文件内容
FROM golang:alpine AS builder
MAINTAINER scoful
WORKDIR /go/kingProject
COPY . /go/kingProject
ENV GOPROXY https://goproxy.cn,direct
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build main.go
FROM alpine AS runner
WORKDIR /go/kingProject
COPY --from=builder /go/kingProject/main .
COPY --from=builder /go/kingProject/config ./config
EXPOSE 8888
VOLUME ["/go/kingProject/config","/go/kingProject/log"]
ENTRYPOINT ["./main"]
![](http://mmbiz.qpic.cn/mmbiz_png/ytcTQO90QusibnXbgGNOITOVH9tWHBKPicP1qqgYV7W6uibALcePNystF6Kqrj8TdovmGroKsZicF4BdAb6Vg9tsDQ/640?wx_fmt=png)
结果是28.4M,比517M减少了488.6M,再降95%,那个533M是第一级构建生成的
6. 再再优化:使用多级构建+scratch基础镜像 22.8M
再再优化的方向:再极端一点,第二级构建的时候用个空镜像来当基础镜像
Dockerfile文件内容
FROM golang:alpine AS builder
MAINTAINER scoful
WORKDIR /go/kingProject
COPY . /go/kingProject
ENV GOPROXY https://goproxy.cn,direct
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build main.go
FROM scratch AS runner
WORKDIR /go/kingProject
COPY --from=builder /go/kingProject/main .
COPY --from=builder /go/kingProject/config ./config
EXPOSE 8888
VOLUME ["/go/kingProject/config","/go/kingProject/log"]
ENTRYPOINT ["./main"]
![](http://mmbiz.qpic.cn/mmbiz_png/ytcTQO90QusibnXbgGNOITOVH9tWHBKPicBP7SaQVFMOVgJDCiahGGjLmyoBDsICZ1T2MCvBiaWbx5SUyRLFYcklMQ/640?wx_fmt=png)
结果是22.8M,已经约等于不用镜像直接编译出的可执行文件大小了,比28.4M减少了5.6M,再降20%,但用scratch当基础镜像的坏处是没法exec进入容器内部,因为真的就是空镜像,啥都没有,啥都不支持
7. 再再再优化:go编译命令去掉冗余输出 16.3M
再再再优化的方向:再再极端一点,go编译的时候,加上参数 -ldflags="-w \-s",直接去掉一些冗余输出内容
Dockerfile文件内容
FROM golang:alpine AS builder
MAINTAINER scoful
WORKDIR /go/kingProject
COPY . /go/kingProject
ENV GOPROXY https://goproxy.cn,direct
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" main.go
FROM scratch AS runner
WORKDIR /go/kingProject
COPY --from=builder /go/kingProject/main .
COPY
--from=builder /go/kingProject/config ./config
EXPOSE 8888
VOLUME ["/go/kingProject/config","/go/kingProject/log"]
ENTRYPOINT ["./main"]
![](http://mmbiz.qpic.cn/mmbiz_png/ytcTQO90QusibnXbgGNOITOVH9tWHBKPicWNPXh2ywOSEoNk7LHLZTa8lemk3LGEl2vZ58wiaI0iaPQTLTuImiayubw/640?wx_fmt=png)
结果是16.3M,看似比不用镜像直接编译出的可执行文件还小,那是因为直接编译没有加上这个参数,如果加上大小还是差不多的,比22.8M减少了6.5M,再降29%,好了,降无可降了,用1.14G来对比的话,减少了1.12G,足足降了99%,鹅妹子嘤!
8. 最终版:顺便解决时区问题 16.3M
Dockerfile文件内容
FROM golang:alpine AS builder
MAINTAINER scoful
WORKDIR /go/kingProject
COPY . /go/kingProject
ENV GOPROXY https://goproxy.cn,direct
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" main.go
RUN echo "https://mirrors.aliyun.com/alpine/v3.8/main/" > /etc/apk/repositories \
&& echo "https://mirrors.aliyun.com/alpine/v3.8/community/" >> /etc/apk/repositories \
&& apk add --no-cache tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo Asia/Shanghai > /etc/timezone \
&& apk del tzdata
FROM scratch AS runner
WORKDIR /go/kingProject
COPY --from=builder /go/kingProject/main .
COPY --from=builder /go/kingProject/config ./config
COPY --from=builder /etc/localtime /etc/localtime
COPY --from=builder /etc/timezone /etc/timezone
EXPOSE 8888
VOLUME ["/go/kingProject/config","/go/kingProject/log"]
ENTRYPOINT ["./main"]
9. 最最推荐使用版:多级+alpine 21.9M综上所述,scratch镜像有它的缺陷,是一个真的空镜像,不支持很多命令,比如cp,sh等,如果要进入容器内部查东西,都进不去,不适合真实情况,所以还是推荐alpine镜像,很小5M多,可以接受。
Dockerfile文件内容
FROM golang:alpine AS builder
MAINTAINER scoful
WORKDIR /go/kingProject
COPY . /go/kingProject
ENV GOPROXY https://goproxy.cn,direct
RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" main.go
FROM alpine AS runner
WORKDIR /go/kingProject
COPY --from=builder /go/kingProject/main .
COPY --from=builder /go/kingProject/config ./config
RUN echo "https://mirrors.aliyun.com/alpine/v3.8/main/" > /etc/apk/repositories \
&& echo "https://mirrors.aliyun.com/alpine/v3.8/community/" >> /etc/apk/repositories \
&& apk add --no-cache tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo Asia/Shanghai > /etc/timezone \
&& apk del tzdata
EXPOSE 8888
VOLUME ["/go/kingProject/config","/go/kingProject/log"]
ENTRYPOINT ["./main"]
over,Enjoy!!!
链接:blog.csdn.net/Scoful/article/details/120729102
(版权归原作者所有,侵删)
![](http://mmbiz.qpic.cn/mmbiz_png/QFzRdz9libEbNSia38aS1nyasgKQeg87pUWgDAjpibeaYOKsThYfvIsYhIN5voSzTHgrjZw69eDsKjLkUbYXm6XAw/640?wx_fmt=png)