查看原文
其他

2个原则,8个小撇步,带你探究 Dockerfile 在工程实践中的实战技巧!

课代表 Jina AI 2023-03-21
J-Tech Talk由 Jina AI 社区为大家带来的技术分享工程师们将深入细节地讲解具体的问题分享 Jina AI 在开发过程中所积累的经验

没来得及参与本次直播的小伙伴,也可以在 JinaAI 视频号的回放栏,查看直播回放。

【Show Notes】

  • 1 个文件,什么是 Dockerfile,为什么它如此重要

    Dockerfile 是一个用于构建镜像的“工程蓝图”


  • 2 个原则,帮助你深入理解并应用

    带你了解编写基本原则和使用 Tips


  • 经验分享 - Jina AI 如何构建高效且可维护的 Dockerfile

    一步步行动拆解,带你探究 Dockerfile 在工程实践中的实战技巧


🌟 GitHub 获得讲师文档 + 示范代码

    https://github.com/jina-ai/Events


1 个文件

在盖房子的时候,我们会有非常详细的工程设计图,用来描述了房子的各种各样的规格,材料以及如何施工。Dockerfile 就类似于这种工程的蓝图,它指导了在构建镜像的时候,各流程次序是怎样的。
同样,房子一般都是在打好的地基上开始建造, 或者在毛坯房基础上装修,你可以用 FORM 关键字来指定基础镜像,FORM 基石,或者 FORM 毛坯,这里我们推荐使用官方镜像。
# FROM [--platform=<platform>] <image>[:<tag>] [AS <name>] 
ARG  CODE_VERSION=latest # 定义变量 
FROM base:${CODE_VERSION} # 指定基础镜像



2 个原则
  • 镜像越小越好
    • 镜像越小不仅构建速度越快,减少网络带宽开销,还能减少受攻击的可能面。
  • 永远记住你构建的是图层而不是一个镜像
    • 了解实际的存储方式,有镜像分层的概念,对于编写好一个 Dockerfile 文件至关重要。因为 Dockerfile 里的每一条指令都会对应于 Docker 镜像中的一层,每⼀条指令的内容就是描述该层应当如何构建。

行动拆解

1. 使用官方镜像作为基础镜像

选择越恰当的镜像,我们需要做的底层工作就越少。选择官方的镜像,不仅仅是因为它们更小,更可靠,还因为能有更多机会利用机器中已经缓存的镜像。

2. 尽可能使用多阶段构建

多阶段构建一般将 FROM ... AS ... 和 COPY --from 组合使用,它允许在一个 Dockerfile 文件中使用多个 FORM 指令,每个 FORM 指令都可以使用不同的基础,只有最后一条 FROM 指令作为本次构建的基础镜像。COPY --from=0  将第一个阶段拷贝文件到这个新阶段(除了使用数字,也可以给各阶段命名)。也就是说,你可以选择性将工件(Artifacts)从一个阶段复制到另一个阶段,从而只保留想要的内容到最终的镜像。

# syntax=docker/dockerfile:1
FROM golang:1.16 
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=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

3. 合并 Run 指令

镜像层数主要取决于 Run 的次数,一个 Run 指令都会被看作是可缓存的执行单元,合并 Run 指令能够大大减少镜像层数。但经常需要变动的内容,还是建议单起一个 Run 

RUN apt-get update && apt-get install -y \
    bzr \
    cvs \
    git \
    mercurial \
    subversion \
    && rm -rf /var/lib/apt/lists/*

4. 删除用不到的依赖项

Docker 镜像应该尽可能地小,所以在 Dockerfile 中要删除用不到的软件或程序,一方面使得容器体积更小;另一方面,减少了攻击面,使得容器更安全。

5. 善用 .dockerignore

顾名思义,和 .gitignore 文件一样。如果不想某些⽂件被打包到镜像,就可以在根⽬录设置.dockerignore

6. 加入适量的标签

标签(Labels)指令用来给镜像以键值对的形式添加一些元数据(metadata),其的应用场景非常广泛,包括容器的构建,部署,生命周期管理等多流程... 

7. 让镜像假设只有一个 CPU

在虚拟机时代,有守护进程(Daemon Process)的概念。在实际运行工作时,由守护进程启动工作进程(Worker Process)。工作进程的最大数量根据机器 CPU 的数量决定,可以用这种方式来提高 CPU 利用率。

8. 假设容器随时都会被终止

如果 Dockerfile 和应用都是你写的,那么你需要假设构建的容器镜像是可以随时被停止的,这就意味着你需做好状态的管理,以及如何优雅地去停止。

🔗 PPT 文件:https://github.com/jina-ai/Events 【点击 阅读原文 跳转】

Dive
最后推荐使用 Dive,这是一个用于探索 Docker 镜像,减少镜像大小的开源工具。

技术交流、活动分享


教程、干货、讲师 PPT 分享


扫码加入 J-Tech 技术讨论群


更多精彩内容(点击图片阅读)


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存