不知道有人碰到过没有
就是 gitlab ci 的时候,会 build docker image ,再 push 到 registry 上,我用的是公有云 的容器镜像服务,所以希望每次 push 都能做到尽可能小的增量
project 是 java springboot 的工程,每次都会生成一个 jar 包,这个 jar 包大概 200m ,如果
用类似
COPY xxxx.jar /app
这样的 Dockerfile ,每次 jar 这一层就要上传 200m+
所以采用了 jar 包分层的技术,用
$ java -Djarmode=layertools -jar target/xxx.jar extract
得到四个目录,
Step 7/11 : COPY dependencies/ /app
---> 9831e5b6f9ae
Step 8/11 : COPY spring-boot-loader/ /app
---> 82f47422bade
Step 9/11 : COPY snapshot-dependencies/ /app
---> 24658da80ea8
Step 10/11 : COPY application/ /app
---> 6d47ede4decb
这样每次 ci 的时候,前三个目录基本没有变化,这样生成 docker image 的 layer 是不变的 ,每次 push 只会 push step 10 之后的内容
这种方法在本地没有问题 mvn clean package... docker build -t ..., docker push ...显示只需要 push 最后一个 layer
e44c9b0a313a: Pushed
5732f7831cbe: Layer already exists
48d1ef8e0017: Layer already exists
025a15bbce04: Layer already exists
8460ea9541f4: Layer already exists
de24004afe49: Layer already exists
a52fcbff5465: Layer already exists
767f936afb51: Layer already exists
然后在 gitlab ci 里,显示每次还是要 push 多个 layer
看了一下日志,每次 gitlab ci 里 build 的时候,
Status: Downloaded newer image for ccr.ccs.tencentyun.com/.../xx:latest
---> 08909e73839f
Step 2/11 : ENV AppName xxx-system
---> Running in b66bf82ba02d
Step1 的 hash 值是一样的,但是 Step 2 的 hash 值就发生变化了,理论上相同的操作应该产 生相同的 hash 值
1
sadfQED2 2023-07-14 12:06:56 +08:00 via Android
分阶段编译?
|
2
Lax 2023-07-14 12:13:24 +08:00
"理论上相同的操作应该产 生相同的 hash 值" --- 这句话,是那个文档里说的?
|
3
ziwen1943 2023-07-14 12:23:35 +08:00 1
分层逻辑失败变成全量 docker 构建的原因主要有两个,第一是编译用基础镜像每次都会重新下载或者变动,那么第一层就变动了,后续也要重新来,第二种就是删除了历史的 image ,导致分层的逻辑没办法命中历史的缓存层。
结合你上面的情况,我认为是 gitlab-ci 每次编译的时候都启用了一个新环境(可能是 docker 模式的 gitlab-runner )导致编译都是全新编译,但是上传的时候缓存层在 hub 里面存在,然后出现全新打包,缓存上传的局面了。 ( ps 如果是 shell 模式的 gitlab-runner ,你需要看一下.gitlab-ci.yaml 文件里面是不是加了 docker rm 的命令删除旧的镜像,因为我就是这么干的,为了节约磁盘空间,为了全新打包避免遗漏) |
4
liantian 2023-07-14 12:30:15 +08:00 via iPhone 1
别用 docker build…换 buildah 就是啦…
buildah 一次 build 是一层,多余文件清理掉就好。 |
5
iBugOne 2023-07-14 13:05:23 +08:00 via Android 1
docker build --cache-from 拉下来的镜像
docker 默认不会复用拉下来的镜像里的层,所以每次都等于全新 build ,需要用 cache-from 钦点 docker 去尽量复用已有的层 |
6
newaccount 2023-07-14 13:08:52 +08:00
baseimage 不要使用 latest ,固定版本试一下呢?
|
7
xiaobai1213 2023-07-14 13:36:40 +08:00
看一下 gitlab-ci 使用的 runner 模式,有的 runner 模式是不会存储之前的工作空间的,这样就会无法命中缓存层,导致每一次都是全量构建
"理论上相同的操作应该产 生相同的 hash 值" 这个是在官方文档里面看到的吗? 之前有试验过 同样命令同一份代码同一个 maven 打出来的两个 jar 最后算出来的 sha1 都是不一样的...... |
8
Masoud2023 2023-07-14 13:44:18 +08:00
你 Gitlab 里的 docker 根本没配置缓存吧?
不过看这帖子也学习到了,原来 jar 包还能这么拆开。。 |
9
guoguobaba OP @iBugOne best solution
每次 gitlab runner 起的是一个新环境,所以 ci 脚本增加下面的就完美解决了 ``` - docker pull $IMAGE || echo "no image" - docker build --cache-from $IMAGE -t $IMAGE . ``` 看了一下 job 的运行时间,从 109s 下降到 29s 特别是我可以开启我之前购买的屮蛋的天翼云主机做 runner 服务器了,他只有 1m 的带宽,用完成 jar 包的 image 上传要 25 分钟以上,现在每次 ci ,只需要 2-3 分钟了。 |
10
guoguobaba OP 汇报一下,这个问题主要是 gitlab ci 是 docker:dind 对应的/var/lib/docker 目录都从
内存中生成导致每次都需要重新下载 image 所以设置一个 pvc ,缓存/var/lib/cache 就可以了 |