给go项目打最小docker镜像,足足降低99%

给go项目打最小docker镜像,足足降低99%

来源:admin 发布时间:2022-08-17 11:30:34 点击数:


go 项目怎么让 docker 镜像体积减小?本文做了详细介绍。

1. 直接编译得到运行文件 22M

使用的项目源码地址 (https://github.com/scoful/kingProject)

本地直接编译打一个linux运行包




set GOOS=linuxset GOARCH=amd64go build main.go

长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

结果是22M

2. 不编译直接运行的镜像 941M

Dockerfile文件内容


















# 基础镜像,基于golang最新镜像构建FROM golang# 作者MAINTAINER scoful# 全局工作目录WORKDIR $GOPATH/kingProject# 把运行Dockerfile文件的当前目录所有文件复制到目标目录COPY . $GOPATH/kingProject# 环境变量#  用于代理下载go项目依赖的包ENV GOPROXY https://goproxy.cn,direct# 需暴露的端口EXPOSE 8888# 可外挂的目录VOLUME ["/go/kingProject/config","/go/kingProject/log"]# docker run命令触发的真实命令(相当于不编译打包,源代码直接运行)ENTRYPOINT ["go","run","main.go"]

编译镜像后查询结果如下:

长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

结果是941M,基本跟基础镜像golang的大小一致,而且因为没有预先编译,等到运行的时候再编译并拉取依赖包,run起来很慢

3. 编译后的镜像 1.14G





















Dockerfile文件内容# 基础镜像,基于golang最新镜像构建FROM golang# 作者MAINTAINER scoful# 全局工作目录WORKDIR $GOPATH/kingProject# 把运行Dockerfile文件的当前目录所有文件复制到目标目录COPY . $GOPATH/kingProject# 环境变量#  用于代理下载go项目依赖的包ENV GOPROXY https://goproxy.cn,direct# 编译RUN GOOS=linux GOARCH=amd64 go build main.go# 需暴露的端口EXPOSE 8888# 可外挂的目录VOLUME ["/go/kingProject/config","/go/kingProject/log"]# docker run命令触发的真实命令(相当于直接运行编译后的可运行文件)ENTRYPOINT ["./main"]

长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

结果是1.14G,更大了,因为加上了编译过程中拉取的包,但是预先编译,所以直接run,速度很快

4. 优化:使用alpine版本的基础镜像 517M

优化的方向:如果一个镜像在https://hub.docker.com/里能搜到有alpine版本,尽量用alpine版本,相当于是官方提供的最小化可用版本

Dockerfile文件内容




















# 基础镜像,基于golang的alpine版本镜像构建FROM golang:alpine# 作者MAINTAINER scoful# 全局工作目录WORKDIR $GOPATH/kingProject# 把运行Dockerfile文件的当前目录所有文件复制到目标目录COPY . $GOPATH/kingProject# 环境变量#  用于代理下载go项目依赖的包ENV GOPROXY https://goproxy.cn,direct# 编译RUN GOOS=linux GOARCH=amd64 go build main.go# 需暴露的端口EXPOSE 8888# 可外挂的目录VOLUME ["/go/kingProject/config","/go/kingProject/log"]# docker run命令触发的真实命令(相当于直接运行编译后的可运行文件)ENTRYPOINT ["./main"]

长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

结果是517M,比1.14G减少了650.36M,直接降了56%,而且run一样很快

5. 再优化:使用多级构建的镜像 28.4M

再优化的方向:go项目其实只是在build的阶段需要go环境,run的时候是不需要的,那build完后go环境用个alpine版本就行

Dockerfile文件内容






























# 基础镜像,基于golang的alpine镜像构建--编译阶段FROM golang:alpine AS builder# 作者MAINTAINER scoful# 全局工作目录WORKDIR /go/kingProject# 把运行Dockerfile文件的当前目录所有文件复制到目标目录COPY . /go/kingProject# 环境变量#  用于代理下载go项目依赖的包ENV GOPROXY https://goproxy.cn,direct# 编译,关闭CGO,防止编译后的文件有动态链接,而alpine镜像里有些c库没有,直接没有文件的错误RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build main.go

# 使用alpine这个轻量级镜像为基础镜像--运行阶段FROM alpine AS runner# 全局工作目录WORKDIR /go/kingProject# 复制编译阶段编译出来的运行文件到目标目录COPY --from=builder /go/kingProject/main .# 复制编译阶段里的config文件夹到目标目录COPY --from=builder /go/kingProject/config ./config# 需暴露的端口EXPOSE 8888# 可外挂的目录VOLUME ["/go/kingProject/config","/go/kingProject/log"]# docker run命令触发的真实命令(相当于直接运行编译后的可运行文件)ENTRYPOINT ["./main"]

长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

结果是28.4M,比517M减少了488.6M,再降95%,那个533M是第一级构建生成的

6. 再再优化:使用多级构建+scratch基础镜像 22.8M

再再优化的方向:再极端一点,第二级构建的时候用个空镜像来当基础镜像

Dockerfile文件内容
































# 基础镜像,基于golang的alpine镜像构建--编译阶段FROM golang:alpine AS builder# 作者MAINTAINER scoful# 全局工作目录WORKDIR /go/kingProject# 把运行Dockerfile文件的当前目录所有文件复制到目标目录COPY . /go/kingProject# 环境变量#  用于代理下载go项目依赖的包ENV GOPROXY https://goproxy.cn,direct# 编译,关闭CGO,防止编译后的文件有动态链接,而alpine镜像里有些c库没有,直接没有文件的错误RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build main.go



# 使用scratch这个空镜像为基础镜像--运行阶段FROM scratch AS runner# 全局工作目录WORKDIR /go/kingProject# 复制编译阶段编译出来的运行文件到目标目录COPY --from=builder /go/kingProject/main .# 复制编译阶段里的config文件夹到目标目录COPY --from=builder /go/kingProject/config ./config# 需暴露的端口EXPOSE 8888# 可外挂的目录VOLUME ["/go/kingProject/config","/go/kingProject/log"]# docker run命令触发的真实命令(相当于直接运行编译后的可运行文件)ENTRYPOINT ["./main"]

长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

结果是22.8M,已经约等于不用镜像直接编译出的可执行文件大小了,比28.4M减少了5.6M,再降20%,但用scratch当基础镜像的坏处是没法exec进入容器内部,因为真的就是空镜像,啥都没有,啥都不支持

7. 再再再优化:go编译命令去掉冗余输出 16.3M

再再再优化的方向:再再极端一点,go编译的时候,加上参数 -ldflags="-w \-s",直接去掉一些冗余输出内容

Dockerfile文件内容






























# 基础镜像,基于golang的alpine镜像构建--编译阶段FROM golang:alpine AS builder# 作者MAINTAINER scoful# 全局工作目录WORKDIR /go/kingProject# 把运行Dockerfile文件的当前目录所有文件复制到目标目录COPY . /go/kingProject# 环境变量#  用于代理下载go项目依赖的包ENV GOPROXY https://goproxy.cn,direct# 编译,关闭CGO,防止编译后的文件有动态链接,而alpine镜像里有些c库没有,直接没有文件的错误RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" main.go

# 使用scratch这个空镜像为基础镜像--运行阶段FROM scratch AS runner# 全局工作目录WORKDIR /go/kingProject# 复制编译阶段编译出来的运行文件到目标目录COPY --from=builder /go/kingProject/main .# 复制编译阶段里的config文件夹到目标目录COPY --from=builder /go/kingProject/config ./config# 需暴露的端口EXPOSE 8888# 可外挂的目录VOLUME ["/go/kingProject/config","/go/kingProject/log"]# docker run命令触发的真实命令(相当于直接运行编译后的可运行文件)ENTRYPOINT ["./main"]

长治网络安全等级保护,长治等保,长治网安备案,网站制作,网站建站,网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

结果是16.3M,看似比不用镜像直接编译出的可执行文件还小,那是因为直接编译没有加上这个参数,如果加上大小还是差不多的,比22.8M减少了6.5M,再降29%,好了,降无可降了,用1.14G来对比的话,减少了1.12G,足足降了99%,鹅妹子嘤!

8. 最终版:顺便解决时区问题 16.3M

Dockerfile文件内容







































# 基础镜像,基于golang的alpine镜像构建--编译阶段FROM golang:alpine AS builder# 作者MAINTAINER scoful# 全局工作目录WORKDIR /go/kingProject# 把运行Dockerfile文件的当前目录所有文件复制到目标目录COPY . /go/kingProject# 环境变量#  用于代理下载go项目依赖的包ENV GOPROXY https://goproxy.cn,direct# 编译,关闭CGO,防止编译后的文件有动态链接,而alpine镜像里有些c库没有,直接没有文件的错误RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" main.goRUN 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

# 使用scratch这个空镜像为基础镜像--运行阶段FROM scratch AS runner# 全局工作目录WORKDIR /go/kingProject# 复制编译阶段编译出来的运行文件到目标目录COPY --from=builder /go/kingProject/main .# 复制编译阶段里的config文件夹到目标目录COPY --from=builder /go/kingProject/config ./config# 复制编译阶段里的时区文件到目标目录COPY --from=builder /etc/localtime /etc/localtimeCOPY --from=builder /etc/timezone /etc/timezone# 需暴露的端口EXPOSE 8888# 可外挂的目录VOLUME ["/go/kingProject/config","/go/kingProject/log"]# docker run命令触发的真实命令(相当于直接运行编译后的可运行文件)ENTRYPOINT ["./main"]


9. 最最推荐使用版:多级+alpine 21.9M

综上所述,scratch镜像有它的缺陷,是一个真的空镜像,不支持很多命令,比如cp,sh等,如果要进入容器内部查东西,都进不去,不适合真实情况,所以还是推荐alpine镜像,很小5M多,可以接受。

Dockerfile文件内容





































# 基础镜像,基于golang的alpine镜像构建--编译阶段FROM golang:alpine AS builder# 作者MAINTAINER scoful# 全局工作目录WORKDIR /go/kingProject# 把运行Dockerfile文件的当前目录所有文件复制到目标目录COPY . /go/kingProject# 环境变量#  用于代理下载go项目依赖的包ENV GOPROXY https://goproxy.cn,direct# 编译,关闭CGO,防止编译后的文件有动态链接,而alpine镜像里有些c库没有,直接没有文件的错误RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-w -s" main.go

# 使用alpine这个轻量级镜像为基础镜像--运行阶段FROM alpine AS runner# 全局工作目录WORKDIR /go/kingProject# 复制编译阶段编译出来的运行文件到目标目录COPY --from=builder /go/kingProject/main .# 复制编译阶段里的config文件夹到目标目录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"]# docker run命令触发的真实命令(相当于直接运行编译后的可运行文件)ENTRYPOINT ["./main"]

over,Enjoy!!!

链接:blog.csdn.net/Scoful/article/details/120729102

(版权归原作者所有,侵删)




长治等保,等保,网络安全,网络等保,等级保护,网络安全等保,网络安全等级保护,长治网络安全等级保护,等保公司,等保测评,等级保护2.0,定级,定级备案,等保备案,长治等保备案,山西等保备案,系统测评,系统备案,网安备案,等保备案服务,等保咨询,公安局备案,二级等保,三级等保,三级测评,系统整改,做等保的公司,网站建设,企业网站建设,企业网站开发,企业网站运维,Linux系统运维,Windows系统运维,服务器运维,环境部署,环境搭建,私有云存储

Powered by 园鉴科技 ©2021-2024  www.anycastyun.com

首 页
产 品
方 案
客 服