以go项目为例
首先我们下看一下直接打包的程序有多大
[$] <git:(master*)> go build -o ./bin/app .
[$] <git:(master*)> ls -lh bin
total 13M
-rwxrwxr-x 1 liyang liyang 13M Jul 24 14:02 app
可以看到,只有13M
然后我们再来看一个没经过优化的的Dockerfile打包出来的镜像
FROM golang:1.18
WORKDIR /usr/src/app
COPY go.mod go.sum ./
RUN export GOPROXY=https://proxy.golang.com.cn,direct && go mod download && go mod verify
COPY . .
RUN go build -v -o /usr/local/bin/app .
CMD ["app"]
打包出来的镜像竟然有1GB多,原因是镜像里包含了go镜像内容和所有编译所用到的工具/源码等
REPOSITORY TAG IMAGE ID CREATED SIZE
bdfdc default 244a313c3bac 24 seconds ago 1.09GB
下一步使用ubuntu中间镜像来优化镜像体积
FROM golang:1.18 as buildstage
WORKDIR /usr/src/app
COPY go.mod go.sum ./
RUN export GOPROXY=https://proxy.golang.com.cn,direct && go mod download && go mod verify
COPY . .
RUN go build -v -o /usr/local/bin/app .
FROM ubuntu
COPY --from=buildstage /usr/local/bin/app /usr/local/bin/app
CMD ["app"]
REPOSITORY TAG IMAGE ID CREATED SIZE
bdfdc ubuntu 8f002a76c331 26 minutes ago 85.5MB
镜像一下减少到85.5MB,已不足原来的1/10,用下面的命令运行是没问题的
docker run dbdfc:ubuntu
但是还是不够小,如果把ubuntu镜像换成alpine可以更进一步优化体积,我们把上面的FROM ubuntu
改成FROM alipine
,其他地方保持不变,重新打包镜像,发现镜像已经减小到了18.3MB
EPOSITORY TAG IMAGE ID CREATED SIZE
bdfdc alpine a9073c5ba036 8 minutes ago 18.3MB
但是这个时候出现了一个问题,运行的时候报错了
[$] <git:(master*)> docker run --rm bdfdc:alpine
exec /usr/local/bin/app: no such file or directory
不要怀疑路径的问题,因为我已经到容器里检查过了
原因是由于alpine镜像使用的是musl libc而不是gnu libc,/lib64/ 是不存在的。但他们是兼容的,可以创建个软连接过去,在创建镜像是增加这条命令RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
此部分参考了https://www.cnblogs.com/yangzp/p/14609641.html
FROM golang:1.18 as buildstage
WORKDIR /usr/src/app
COPY go.mod go.sum ./
RUN export GOPROXY=https://proxy.golang.com.cn,direct && go mod download && go mod verify
COPY . .
RUN go build -v -o /usr/local/bin/app .
FROM alpine
COPY --from=buildstage /usr/local/bin/app /usr/local/bin/app
RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
CMD ["app"]
这个一个精简版的镜像就做好了.
当然还可以继续优化,比如用第二个基础镜像使用scratch
,使用这个镜像比使用alpine可以再减小5MB左右,打包成功的镜像竟然比直接打包项目还小.但是里面确缺少了很多基础的命令/工具/库,甚至连sh都没有,给后面的调试带来了很多麻烦,在一个程序几十几百兆的项目中,这5MB的开销不值得一提
REPOSITORY TAG IMAGE ID CREATED SIZE
bdfdc alpine e295e34e5afb 7 minutes ago 18.3MB
bdfdc scratch 0c295c729d99 About an hour ago 12.7MB