容器管理:Docker:如何编写高效的Dockerfile

tlin82大约 2 分钟devopsdockerdocker容器管理技巧Dockerfile多阶段构建

前言

Dockerfile是建立Docker镜像的基础描述文件,了解和学习怎么高效编写Dockerfile。

一个高效的Dockerfile,最终实现的目标是可以构建出更小的镜像,加快构建速度。

正文

  • 尽量使用国内的基础镜像
  • 尽量使用小的、够用基础镜像;
  • 尽量排除掉无关的目录文件;
  • 减少和控制Docker Layer层数量;
  • 把不变层放到前面,可变层放到后面;
  • 使用多阶段来分离build和runtime;

尽量使用国内的基础镜像

因为网络原因,使用国内基础镜像源毋庸置疑会加快构建速度。

  • 例如,使用From指令指定使用阿里云或本地先docker pull
From registry.cn-beijing.aliyuncs.com/yournamespace/openjdk:8-jdk-alpine;

尽量使用小的,够用基础镜像

可以考虑使用各种alpine镜像,但要注意一些已知问题

尽量排除掉无关的目录文件

  • 不要放入无关的文件到构建目录;
  • 可以使用 .dockerignore 来忽略这些文件

减少和控制Docker Layer层数量

  • 多条RUN指令可以使用&&连接起来作为一条指令执行。因为一条指令就是加一层。例如:
RUN yum install -y git &&  yum install -y nginx
  • 如有安装应用,适当清理缓存数据。例如:
FROM centos
RUN yum install -y git && \
    yum install -y nginx && \
    yum clean all && rm -rf /var/cache/yum/*

不变层的指令放到前面,常变层放到后面

这样做的原因是,不变层可以缓存,下次构建可以复用,节省带宽和时间。

使用多阶段来分离build和runtime (重要)

使用多阶段得方式,可以大大降低镜像大小。实现应用构建环境和运行环境分离,最终只需要把运行环境的依赖打包到应用镜像中。

在Dockerfile中使用多个FROM声明,每个FROM声明可以使用不同的基础镜像

例如:

FROM golang:1.17.6 AS BUILDER
ADD . /go/src/github.com/golang/example
RUN go build -o /go/src/github.com/golang/example/hello /go/src/github.com/golang/example/hello/hello.go

FROM golang:1.17.6-alpine
WORKDIR /go/src/github.com/golang/example
COPY --from=BUILDER /go/src/github.com/golang/example/hello /go/src/github.com/golang/example/hello
ENTRYPOINT ["/go/src/github.com/golang/example/hello"]

  • 两条FROM指令,意味两个阶段。
  • 第一条FROM指令时应用构建阶段,并使用关键字AS来命名应用构建阶段 "BUILDER"。
  • 第二条FROM指令起则是运行Runtime阶段,并使用COPY --from=BUILDER 把应用构建结果加入到应用镜像中,不需要的例如SDK则抛弃。

参考