当前位置: 首页 > 科技观察

再见 Docker,是时候拥抱下一代镜像构建工具 Earthly 了

时间:2023-03-14 14:52:27 科技观察

再见Docker,是时候拥抱下一代镜像构建工具Earthly了。Earthly是一个更高级的Docker镜像构建工具。Earthly用自己定义的Earthfile替换传统的Dockerfile来完成镜像构建;Earthfile就像Earthly的官方描述:Makefile+Dockerfile=Earthfile目前强依赖于buildkit,Earthly通过buildkit支持Dockerfile的一些扩展语法,并整合了Dockerfile和Makefile,让跨平台构建和编码Dockerfile变得更简单;使用Earthly可以更方便的完成Dockerfile代码复用和更友好的CI自动集成。2.快速启动2.1。安装依赖Earthly目前依赖Docker和Git,所以在安装Earthly之前请确保机器上已经安装了Docker和Git。2.2.安装EarthlyEarthly是用Go编写的,所以它主要是一个二进制文件。linux下安装可以直接参考官方安装脚本:$sudo/bin/sh-c'wgethttps://github.com/earthly/earthly/releases/latest/download/earthly-linux-amd64-O/usr/local/bin/earthly&&chmod+x/usr/local/bin/earthly&&/usr/local/bin/earthlybootstrap--with-autocomplete'安装完成后Earthly会启动一个buildkitd容器:earthly-buildkitd。2.3.语法高亮目前,Earthly官方支持VSCode、VIM和SublimeText编辑器的语法高亮。具体如何安装请参考官方文档[1]。2.4.基础使用本例来源于官方Basic教程。下面以编译一个Go项目为例:首先创建一个目录,名称任意,目录下有项目源文件和一个Earthfile文件;main.gopackagemainimport"fmt"funcmain(){fmt.Println("helloworld")}EarthfileFROMgolang:1.17-alpineWORKDIR/go-examplebuild:COPYmain.go.RUNgobuild-obuild/go-examplemain.goSAVEARTIFACTbuild/go-example/go-exampleASLOCALbuild/go-exampledocker:COPY+build/go-example.ENTRYPOINT["/go-example/go-example"]SAVEIMAGEgo-example:latest有了Earthfile,我们就可以使用Earthly将其打包为镜像;#目录结构~/t/earthlytest???树。├──Earthfile└──main.go0directories,2files#通过earthly构建~/t/earthlytest???earthly+docker构建完成后,我们可以直接从docker镜像列表中查看新建的镜像,运行:3.高级使用3.1.多阶段构建Earthfile包含类似于Makefile的目标。也可以通过特定的语法来引用不同的目标。每个目标都可以独立执行。Earthly会在执行过程中自动解决这些依赖关系。关系。这种多阶段构建的语法非常灵活,我们可以在每个阶段运行独立的命令并使用不同的基础镜像;正如你从快速入门中看到的,我们总是使用一个基础镜像(golang:1.17-alpine),对于像Go这样使用自己的运行时编译并且不依赖于它的语言SDK的应用程序,我们实际上可以把“在一个简单的运行时系统镜像中发布”,从而减小最终镜像的大小:由于使用了多个目标,所以我们可以单独运行构建目标来验证我们的编译过程。这种多目标设计方便我们在构建应用时细化编译打包步骤,也方便我们进行单独的验证。比如我们单独执行buildtarget来验证我们的编译过程是否正确:其他阶段的验证完成后,我们可以直接运行最终的target,earthly会自动识别这个依赖并自动运行其依赖的target:3.2,扩展指令3.2.1。SAVESAVE指令是Earthly本身的扩展指令,实际上分为SAVEARTIFACT和SAVEIMAGE;SAVEARTIFACT指令格式如下:SAVEARTIFACT[--keep-ts][--keep-own][--if-exists][--force][][ASLOCAL]SAVEARTIFACT指令用于将文件或目录从构建运行时环境保存到目标工件环境;保存到artifact环境后,可以通过COPY等命令在其他地方引用,类似于Dockerfile的COPY--from...语法;不同的是SAVEARTIFACT支持ASLOCAL附加参数,一旦指定该参数后,earthly会同时将文件或目录复制到宿主机,一般用于调试等用途。上例中显示了SAVEARTIFACT命令。运行earthly+build命令后,你会在本地实际看到SAVEARTIFACT:而另一个SAVEIMAGE命令主要用于保存当前构建环境对于一个IMAGE,如果指定了--push选项并且--push选项为执行earthly+target命令时添加,镜像会自动推送到目标Registry。SAVEIMAGE指令格式如下:SAVEIMAGE[--cache-from=][--push]...3.2.2、GITCLONEGITCLONE指令用于克隆指定的git仓库搭建环境;与RUNgitclone...命令不同的是,GITCLONE通过宿主机的git命令运行,不依赖于容器中的git命令,也可以直接为earthly配置git认证,从而避免了这些安全信息泄漏到构建环境中;earthly的git认证如何配置,请参考官方文档[2];以下是GITCLONE命令的示例:3.2.3。COPYCOPY命令类似于标准的DockerfileCOPY命令,除了它支持Dockerfile标准的COPY功能之外,earthly中的COPY命令可以引用其他目标链接中生成的artifacts,依赖关系会在时自动声明引用;也就是说,当Btarget中有类似COPY+A/xxxxx/path/to/copy的命令时,如果简单的执行earthly+B,那么earthly会根据依赖关系断定targetA需要在COPY之前执行分析。COPY指令的语法格式如下:#与Dockerfile的用法相同,从上下文复制COPY[options...]...#扩展支持从目标复制COPY[options...]...3.2.4,RUNRUN命令在标准使用方面与Dockerfile一致,除了增加了更多的扩展选项外,命令格式如下:#shell模式操作(/bin/sh-c)RUN[--push][--entrypoint][--privileged][--secret=][--ssh][--mount][--]#exec模式运行RUN[[...],"","","",...]其中--privileged选项允许运行的命令使用特权能力,但是earthly需要在运行目标时添加--allow-privileged选项;--interactive/--interactive-keep选项用于交互执行一些命令,交互完成后继续构建。交互过程中进行的操作会持久化在图像中:限于篇幅,其他具体说明请参考官方文档Earthfilereference[3]。3.3.UDCSUDCs的全称是“User-definedcommands”,即用户自定义命令;通过UDC,我们可以剥离Earthfile中的特定命令,实现更通用、更统一的代码复用;下面是定义UDCs命令的例子:#Command的定义#??注意:语法必须满足以下规则#1,名称全部大写#2,名称带下划线#3,第一个命令必须是COMMAND(后面没有冒号)MY_COPY:COMMANDARGsrcARGdest=./ARGrecursive=falseRUNcp$(if$recursive="true";thenprintf---r;fi)"$src""$dest"#referenceintargetbuild:FROMalpine:3.13WORKDIR/udc-exampleRUNecho"hello">./foo#byDO关键字引用UDCsDO+MY_COPY--src=./foo--dest=./barRUNcat./bar#prints"hello"UDCs不能只定义在一个Earthfile,可以跨文件跨目录引用UDC:有了UDC,我们就可以通过这种方式,将基础镜像的统一版本控制、特殊镜像的通用处理等操作抽象出来,然后根据需要引用各个Earthfile;使用UDC的例子可以参考我的autobuild[4]项目,其中udcs[5]目录下定义了大量常用的UDC,供其他目标镜像的Earthfile批量引用。3.4.多平台构建之前使用Dockerfile时,我们需要自己配置并启动buildkit来实现多平台构建;配置过程可能会很繁琐,但是现在使用earthly可以默认帮助我们实现多平台交叉编译,我们需要做的就是在Earthfile中声明需要支持哪些平台:当上面的Earthfile执行earthly--push+allbuild,会自动构建四个平台的镜像,并保持一个tag。同时,由于使用了--push选项,也会自动推送到DockerHub:4.总结Earthly弥补了Dockerfile的诸多不足,解决了诸多痛点;但也可能需要一定的学习成本,但如果你已经熟悉Dockerfile,学习成本其实并不高;所以还是比较推荐把Dockerfile换成Earthfile来统一和版本化管理。由于本文篇幅有限(偷懒),很多地方没有涉及,比如共享缓存等,所以更详细的Earthly使用方法最好仔细阅读官方文档[6]。