作者:崔力强

在之前使用云效进行镜像构建时,你可能会遇到如下问题:

  1. 只能对一个 Registy 进行 login,如果 FROM 的 image 和 push 的 image registry 不相同,则无法实现。
  2. 镜像构建缓存基于 oss 实现,有 5G 的大小限制,如果缓存过大,就无法使用。且每次全量上传缓存,耗时较长。为了解决上述问题,云效流水线对镜像构建能力做了如下增强:
  • 提供了镜像 Registry 的 Login 和镜像构建并推送两类步骤,以提高灵活性。比如,支持 FROM Image 和构建出来的目标 Image 来自不同的私有镜像仓库的场景。
  • 基于 buildx 提供标准、透明且灵活的的镜像缓存管理机制。如果是私有构建机器,可以选择本地缓存;如果是在公共构建集群,则可以采用远端的 Registry 作为缓存存储。
  • 基于 buildx 提供了多架构镜像构建能力,简单的添加一个参数,就可以同时构建 amd64 和 arm64 两种 CPU 架构的镜像。两个镜像共享同一个镜像地址,在不同架构的机器上拉取镜像时候,会自动拉取对应架构的镜像。

需要注意的是,为了使用上述新能力,需要在构建任务的构建环境中选择“指定容器构建”。如果是私有构建机器的话,需要选择在“默认 VM 环境”上构建。

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_缓存

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_缓存_02

使用了这两种配置之后,就可以选择到上面这些能力增强。

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_缓存_03

并且可以在步骤运行的日志中看到这些步骤所对应的代码库地址:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_docker_04

查看源码,就可以了解该步骤的实现细节。

镜像 Registry Login 与镜像构建的解耦

假设有这个场景,你有两个阿里云账号,A 和 B。

A 账号下有一个镜像作为镜像构建的基础镜像,是私有镜像,地址如下,其中包含了 Java 程序运行的基础软件。

registry.cn-beijing.aliyuncs.com/hub-mirrors/openjdk:8-jdk-alpine

B 账号下有一个镜像作为应用镜像,也是私有镜像,地址如下:

registry.cn-hangzhou.aliyuncs.com/yunxiao-demo/app1

该镜像的 Dockerfile 如下,来自代码库:<https://atomgit.com/flow-example/spring-boot/blob/master/Dockerfile5>

# 基础镜像来自A账号,构建出来的镜像 registry.cn-hangzhou.aliyuncs.com/yunxiao-demo/app1 会推送到B账号
FROM registry.cn-beijing.aliyuncs.com/hub-mirrors/openjdk:8-jdk-alpine

# 下面这行COPY是为了验证缓存是否生效用的
COPY deploy.sh deploy.sh

# 下面这行COPY,因为每次构建出来的jar包都不相同,因此不会走缓存
COPY target/application.jar app.jar

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

在这个镜像构建步骤前,需要有一个 Java 构建的步骤来产生这个 target/application.jar 文件。

在老版的构建步骤则存在问题。在原有的镜像构建步骤中,docker login 和 docker build 是在同一个步骤中的进行 的,如下图所示:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_缓存_05

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_缓存_06

login 和 build 两个动作耦合起来了,一个 build 只能搭配一个 login。考虑上述的场景,FROM 镜像和构建目标镜像来自不同的账号,且都是私有镜像,则无法实现。

使用新的步骤,就可以实现了,如下图的配置所示:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_缓存_07

运行的日志如下,两个登录步骤都会在镜像构建步骤中生效。

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_docker_08

使用 Registry 作为镜像缓存存储

在上面的例子中,日志的最后部分输出:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_jar_09

这表明构建缓存上传到我的 Registry 了,也就是:

registry.cn-hangzhou.aliyuncs.com/yunxiao-demo/app1:flow-docker-build-cache

这是镜像构建的默认配置,让我们回过头来再看下构建配置,进行确认:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_jar_10

这里选择了“远端缓存”,默认使用目标镜像,tag 是 flow-docker-build-cache。在下一次运行镜像构建时,就会重用这个缓存,然后基于这个缓存进行构建。让我们看下下一次的构建日志:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_jar_11

可以看到,构建尝试从 registry.cn-hangzhou.aliyuncs.com/yunxiao-demo/app1:flow-docker-build-cache 中拉取缓存,并且未修改的层会直接使用缓存。

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_jar_12

在这个例子中,只有两个步骤,第一个步骤耗时不长,使用缓存与否并没有带来时间上的差异,且拉取缓存本身也是需要花时间的。因此需要结合拉取缓存的时间与缓存节省时间进行综合考量。

此外还可以通过使用 VPC Registry 地址来加速缓存的拉取和上传。由于云效在大陆地区只有北京的构建集群,因此如果你的目标镜像是在北京的,则可以使用 VPC 地址来替换公网地址来达到加速的效果。

对于上面的例子,目标镜像是在杭州的,在北京的云效公共构建集群上无法通过 VPC 地址来访问杭州的 Registry,该怎么办呢?

也是有办法的,修改构建配置,让缓存不要存储到默认的杭州目标 Registry 中,而是配存储到北京镜像 Registry 的 VPC 镜像地址。这里我们使用上面提到的北京的基础镜像地址作为缓存存储的目标,如下所示:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_jar_13

在远端缓存中填写地址如下:registry-vpc.cn-beijing.aliyuncs.com/hub-mirrors/openjdk:app1-flow-cache

表明在构建过程中产生的缓存会被存储到到这个镜像的特定的 tag,app1-flow-cache 上。表明这个 tag 是给 app1 这个应用的缓存使用的。

然后还需要做两个调整,使得构建过程中镜像拉取和镜像缓存存储都使用这个 VPC 地址,从而加快构建速度。

1)账号的 A 的 login 地址也要改成这个 VPC 的地址

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_jar_14

2)Dockerfile 中的 FROM 也要改成这个 VPC 的 registry 地址

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_docker_15

再次观察日志,可以看到构建过程会从 vpc 地址上传和下载缓存:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_jar_16

使用本机作为缓存存储

如果你使用私有构建机的话,则推荐使用“本地缓存”的选项。docker 构建会直接本地的 docker deamon 来进行构建,因此会使用本地缓存。

配置如下所示:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_缓存_17

查看日志会发现,可以看到命令中没有指定特别的缓存方式,所以使用的默认值就是本地缓存。运行两次之后可以看到被缓存的层。

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_jar_18

构建多架构镜像

一个镜像包含了 CPU 架构的属性,在 amd64 芯片的机器上构建产出的镜像在 arm64 的机器上将无法启动。如果你的镜像需要同时在 amd64 和 arm64 等不同的芯片架构上使用,那么可以轻松的在云效上构建出来多架构的镜像。

云效基于 buildx 提供多架构构建能力,只需要添加一个 --platform 的参数即可。基于上面的示例,我们只需修改配置如下:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_jar_19

添加“更多构建参数”--platform linux/amd64,linux/arm64

查看日志,可以看到每个构建步骤都会同时构建 amd64 和 arm64 两个版本:

更快、更灵活、场景更丰富,云效镜像构建能力升级啦!_缓存_20

在这次构建中,会产生一个镜像地址:registry.cn-hangzhou.aliyuncs.com/yunxiao-demo/app1:2024-09-19-12-24-56,但实际包含的是两个镜像。当从 arm64 的机器上进行拉取,则拉取的就是 arm64 版本的镜像,当从 amd64 的机器上进行拉取,则拉取的就是 amd64 版本的镜像。

总结

云效镜像构建能力的增强,得益于几个方面:

欢迎点击此处,前往云效流水线 Flow(flow\.aliyun.com)进行体验!