docker镜像存储结构介绍
docker镜像是一层一层堆砌出来的,镜像支持最大数层数是127。每一层包含了dockerfile中命令执行的结果,后面的Layer没办法修改前面的Layer,编译镜像类似于git 的提交,这样设计的好处是多个镜像可以共用基础层,节省存储空间,加速拉取时间。不过这样的存储结构同时也不利于空间优化,不了解结构的基础下可能造成文件删除体积也没减小,修改个文件权限镜像体积暴增的困惑。
镜像优化
下面所有的优化都是基于docker镜像的特殊存储结构
-
不常变动的部分写在dockerfile上面,以便后续变更时可以利用缓存,减少build时间。
-
编写 .dockerignore
编译镜像时,docker 先要准备编译用的context,默认情况下会把 Dockerfile所在的所在文件夹下所有文件包含进去,如果不想把src目录包含进去来加快编译速度,可以添加.dockerignore,内容如下src/
-
RUN rm xxx
删除前面层的文件不会减小镜像大小,因为包含文件的那层会一直存在。 -
尽量不在dockerfile去修改文件权限,修改权限后的文件会生成一份新的文件导致镜像变大,修改权限最好本地直接改好或写在启动脚本中(不推荐)。
-
只复制需要的,如果可能,避免复制。在将文件复制到镜像中时,请确保对要复制的内容非常明确,避免
COPY . /home/admin/broker
这样的操作,使用COPY app/xxx.jar /home/admin/broker
-
添加文件夹到指定目录,最好填写
绝对路径
,如果想把kafka文件夹添加到home,要写成ADD kafka/ /home/kafka/
-
大的rpm包,如果要安装到镜像中,可以做成yum 源,yum install xx之后yum clean all,如果ADD XX.rpm /xx,这样rpm会使镜像增大。
-
大的压缩包最好是做成可以下载的文件,下载解压后删除源文件
-
多个RUN或者ENV最好合并为一个,这样生成的文件都在同一层,便于优化大小
-
去掉不必要的组件,比如
yum install vim
不安装运行不必须得vim,可以减小镜像体积 -
每次RUN的后面阶段删除不必要的文件,比如 yum install xx 安装软件后要执行
yum clean all
清除缓存,减小镜像。 -
基础镜像要指定明确的版本
FROM openjdk:latest建议使用FROM openjdk:8-jre-alpine
-
基础镜像如果可能,劲量使用官方发布的版本,第三方的版本有被植入病毒的风险,而且没法保证及时补丁升级和更新
-
基础镜像劲量选择小体积的发行版本,比如基于
alpine linux
制作的镜像, -
分阶段编译,docker 17.05 版本以后开始支持分阶段编译,可以使用编译镜像去编译,生成的目标文件导入到运行环境镜像中,这样编译出的镜像就可以不需要一些编译工具,编译依赖,去掉编译中产生的无用文件
-
WORKDIR 为
RUN CMD ENTRYPOINT
指定一个默认的工作目录 -
启动脚本中最好使用
exec
去运行程序 -
使用LABEL去添加一些附属信息,比如作者,联系方式,内部软件版本之类
-
使用HEALTHCHECK添加健康检查,判断拉起的容器业务是否正常
FROM golang:1.7.3 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]
实践证明,选择一个小的基础镜像,分阶段编译是最有效的优化手段,可以自己动手尝试一下
引用
https://docs.docker.com/develop/develop-images/multistage-build/
https://blog.alexellis.io/mutli-stage-docker-builds/
http://blog.thoward37.me/articles/where-are-docker-images-stored/
https://segmentfault.com/a/1190000017579626
https://github.com/GoogleContainerTools/distroless