背景
我的项目之前托管在 Github 上面
Dockerfile 是我自己写的,用了最新的 --mount
语法,缓存效果非常好,都不需要再专门加一层用来缓存依赖,直接跟本地跑一样快。还用了 Spring 分层插件,镜像的增量也只会有新增的部分。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
FROM maven:3.9-eclipse-temurin-17-alpine AS build
WORKDIR /app
COPY pom.xml ./pom.xml
COPY src ./src
RUN --mount=type=cache,target=/root/.m2 \
mvn package -am -DskipTests
RUN --mount=type=cache,target=/root/.m2 \
mkdir -p /layers && \
cp /app/target/$(mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout)-$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout).jar /layers/target.jar && \
cd /layers && \
java -Djarmode=layertools -jar /layers/target.jar extract
FROM eclipse-temurin:17-jre AS runtime
WORKDIR /app
COPY --from=build /layers/dependencies/ .
COPY --from=build /layers/snapshot-dependencies/ .
COPY --from=build /layers/spring-boot-loader/ .
COPY --from=build /layers/application/ .
EXPOSE 8080
# 执行命令
ENTRYPOINT [ "java", "org.springframework.boot.loader.launch.JarLauncher" ]
|
构建 docker 镜像用的 Github 官方给的 workflow,一整套下来,真的很漂亮
后来,因为一些原因,仓库迁移到自建的 Gitea 上来了,入乡随俗,也就用上了 Gitea Action,各种问题便接踵而至
问题
镜像构建缓慢
问题的表面原因显而易见,每一次都去下载了完整的 Maven 依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Progress (5): 0.7/1.6 MB | 328/459 kB | 0.4/1.9 MB | 95/862 kB | 850/855 kB
Progress (5): 0.7/1.6 MB | 328/459 kB | 0.4/1.9 MB | 95/862 kB | 855 kB
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/httpcomponents/core5/httpcore5/5.2.4/httpcore5-5.2.4.jar (855 kB at 663 kB/s)
#10 252.7 Downloading from central: https://repo.maven.apache.org/maven2/org/apache/httpcomponents/core5/httpcore5-h2/5.2.4/httpcore5-h2-5.2.4.jar
#10 252.7 Progress (4): 0.7/1.6 MB | 328/459 kB | 0.4/1.9 MB | 95/862 kB
Progress (4): 0.7/1.6 MB | 328/459 kB | 0.4/1.9 MB | 95/862 kB
Progress (4): 0.7/1.6 MB | 328/459 kB | 0.4/1.9 MB | 95/862 kB
Progress (4): 0.7/1.6 MB | 328/459 kB | 0.4/1.9 MB | 112/862 kB
Progress (4): 0.7/1.6 MB | 328/459 kB | 0.4/1.9 MB | 112/862 kB
Progress (4): 0.7/1.6 MB | 328/459 kB | 0.4/1.9 MB | 128/862 kB
Progress (4): 0.7/1.6 MB | 328/459 kB | 0.5/1.9 MB | 128/862 kB
|
这玩意下载的又慢,又多,还都是单线程下载,日志还拉个几千行,很难不让人血压升高
镜像无法重用
就是,每一次构建镜像,好像都需要从 Dockerhub 上面重新拉去基础镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#7 [build 2/5] WORKDIR /app
#7 sha256:64f0f61b31342293811c4e3ccb537233fcfe562ca06fad9d8d812301a43cf66a 93B / 93B 0.0s done
#7 sha256:4f4fb700ef54461cfa02571ae0db9a0dc1e0cdb5577484a6d75e68dc38e8acc1 32B / 32B 0.1s done
#7 sha256:a6bac109506e0e8259f57335eb13f11e48c16a2031d39442b3be200c45ba239a 156B / 156B 0.1s done
#7 sha256:2152833668d7f665efae9f5901512719f4b0269a34ec568bd055db5ece013406 858B / 858B 0.1s done
#7 sha256:538a095b96fac90e1a596046e0c0d4d75aa1451f8f278cdfbe5148c9ea35b5d7 2.11kB / 2.11kB done
#7 sha256:96e3299f059b933428266eb1e665628370ebb22006295cae5f33b8294545ba3d 160B / 160B 0.0s done
#7 sha256:25f66cc26682c59c201a46f3a75c16ecf546862e732efbbdccae66e8aa736c71 4.24MB / 4.24MB 0.1s done
#7 sha256:a531e50593c7123d3ba2c82b61f41d8c5a32b3d4cd17045cf97b5bf64a71ecfe 9.17MB / 9.17MB 0.2s
#7 sha256:68a797ec6e8389f8017685a5168b0bcd0ebec6f42e3bfb325a3f260d56afc8b5 23.07MB / 144.39MB 0.2s
#7 sha256:591c34627c847892ee87160ccb0488eb4484039dd04d400e9e86561f15459495 14.03MB / 14.03MB 0.2s
#7 sha256:43c4264eed91be63b206e17d93e75256a6097070ce643c5e8f0379998b44f170 3.62MB / 3.62MB 0.2s
#7 sha256:a531e50593c7123d3ba2c82b61f41d8c5a32b3d4cd17045cf97b5bf64a71ecfe 9.17MB / 9.17MB 0.3s done
#7 sha256:68a797ec6e8389f8017685a5168b0bcd0ebec6f42e3bfb325a3f260d56afc8b5 50.33MB / 144.39MB 0.3s
#7 sha256:43c4264eed91be63b206e17d93e75256a6097070ce643c5e8f0379998b44f170 3.62MB / 3.62MB 0.3s done
#7 sha256:68a797ec6e8389f8017685a5168b0bcd0ebec6f42e3bfb325a3f260d56afc8b5 105.91MB / 144.39MB 0.6s
#7 sha256:68a797ec6e8389f8017685a5168b0bcd0ebec6f42e3bfb325a3f260d56afc8b5 132.12MB / 144.39MB 0.8s
#7 sha256:591c34627c847892ee87160ccb0488eb4484039dd04d400e9e86561f15459495 14.03MB / 14.03MB 0.6s done
#7 extracting sha256:43c4264eed91be63b206e17d93e75256a6097070ce643c5e8f0379998b44f170
#7 sha256:68a797ec6e8389f8017685a5168b0bcd0ebec6f42e3bfb325a3f260d56afc8b5 144.39MB / 144.39MB 0.9s
#7 extracting sha256:43c4264eed91be63b206e17d93e75256a6097070ce643c5e8f0379998b44f170 0.1s done
#7 extracting sha256:591c34627c847892ee87160ccb0488eb4484039dd04d400e9e86561f15459495
#7 sha256:68a797ec6e8389f8017685a5168b0bcd0ebec6f42e3bfb325a3f260d56afc8b5 144.39MB / 144.39MB 3.2s done
#7 extracting sha256:591c34627c847892ee87160ccb0488eb4484039dd04d400e9e86561f15459495 2.5s done
#7 extracting sha256:68a797ec6e8389f8017685a5168b0bcd0ebec6f42e3bfb325a3f260d56afc8b5
#7 extracting sha256:68a797ec6e8389f8017685a5168b0bcd0ebec6f42e3bfb325a3f260d56afc8b5 1.9s done
#7 DONE 5.7s
|
分析
显而易见,是缓存的问题,原先在Github(其实也有问题,只不过网速快,感觉不到)本地跑的好好的,怎么到自己平台上面跑就这么多问题。
前者很明显是我的 —moun
t 缓存没有生效,于是开始查文档
Docker buildx 参数分析
找到 这篇文档,再看到我的 workflow
1
2
3
4
5
6
7
8
9
10
|
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
|
注意到cache-from: type=gha
cache-to: type=gha,mode=max
这两个参数,好像是和 action 的 cache server 有关的,可能我是 Gitea 所以不支持吧,所以尝试换了其他的参数 inline
和 local
没有啥意义,registry
试了用 Gitea Registry,不行(回看时,觉得可能是 这个参数的问题)
Gitea Action Cache Server 配置
既然改配置不行,那就去看看能不能给 Gitea Action 配一个 cache server
然后是这一篇 博客,讲到了加上这个 env 就有缓存功能
1
2
3
4
5
|
jobs:
build:
env:
RUNNER_TOOL_CACHE: /toolcache
...
|
不过可惜,这个是 clone action script 和其他的缓存,不是我要的 cache server
最后,仔细看,发现博客引用了这个 链接
Configuring cache when starting a Runner using docker image
哦哦哦,原来我的 act_runner 在 docker 里面跑的,要端口映射并且加配置,workflow 才能找到 cache server
于是,爽快的配置好,然后,问题依旧。。。
检索 issue
这个时候就感觉,可能是 —mount
的问题吧,因为前面的镜像都提示有缓存的,但就是每一次到了mvn package
的时候,就去下载依赖了。
其实,有一个解决方法,就是用原来的方式,把依赖作为一个层放进去,但是我就是不想那样做✊
我相信,这个问题,不只有我一个人遇到,于是去检索 issue
找到了 这个
似乎是官方不是很好解决,但是下面有人指路到 另一个项目:buildkit-cache-dance
看了看,好像就是为了解决 —mount
的缓存而写的。简单来说,就是手动的把—mount
的 cache 保存到主机,然后再用action/cache
缓存到 cache server
检查 Gitea Action cache server
又是爽快的配置好,又是问题依旧
找来其他人仓库的 workflow 仔细对比了,确信写的没问题,便怀疑是 cache server 的问题
简单来说,检查了,没问题
检查 Workflow
这个时候,我才上 GitHub 原来的仓库去看,发现其实原来的仓库也有相似的问题
所以,问题就只有可能出现在 GitHub 给的 workflow 上了
我对着屏幕,睁大眼睛,一行一行的看
视线最终停留在 docker/setup-buildx-action
这个 action 上面
真相大白
好了,不卖关子了
我们知道,现代化的 Docker 是有很多个模块组成的,容器的构建部分主要是由 buildx
负责的。我们平常使用的docker build
命令,实际上是用的 docker 自带的 buildx
进行构建镜像操作的。但 buildx
其实可以独立工作,独立完成拉取基础镜像,构建,推送等工作。
而 docker/setup-buildx-action
这个 action,就是创建一个独立的 buildx,并且把当前的 docker cli 的构建引擎设置为新创建的
因此,容器的构建工作都会在一个独立的容器里面完成
1
2
3
4
5
6
7
|
root@ubuntu-42:~/gitea# docker ps
CONTAINER ID IMAGE COMMAND NAMES
8f5ab8cd820a moby/buildkit:buildx-stable-1 "buildkitd --allow-i…" buildx_buildkit_builder-e4308f9d-5be1-4724-aebf-5a42bd36ecf50
e73ffb9ff9ee gitea/runner-images:ubuntu-latest "/bin/sleep 10800" GITEA-ACTIONS-TASK-160_WORKFLOW-Java-CI-with-Maven_JOB-build
48b9f06f0cc3 moby/buildkit:buildx-stable-1 "buildkitd --allow-i…" buildx_buildkit_builder-4d03a86d-a95d-4021-8775-97153798d54f0
208ebdade2df gitea/act_runner:nightly "/sbin/tini -- /opt/…" gitea-runner-1
fd636dc949b0 moby/buildkit:buildx-stable-1 "buildkitd --allow-i…" buildx_buildkit_builder-f0901d6f-19eb-4ec3-af8a-4b6d4f08e3240
|
容器构建都在独立容器里面了,缓存自然就不好搞了。这也解释了上面所说的,每一次构建都要重新拉取镜像的问题
虽然 issue1 issue2 里面有提到,buildx 的数据实际上是在一个命名的卷里面的,没有那么容易丢失。但是管理起来对我来说还是太复杂了
解决方案
把 docker/setup-buildx-action
删掉
对,就是把这个 action 删掉,让容器使用本机的 docker 去构建,这样所有缓存就都留在同一个地方,最后效果非常好,即使需要重新编译,但是整个 workflow 也可以在半分钟内完成
总结
折腾了一晚上。
暴露出来很多的问题。一开始参照就没有选好,GitHub 上也有我遇到的问题,只不过我都选择性忽视了,然后在 gitea 上硬去解决。还有那个缓存的,action/cache
这个 action,在整 buildkit-cache-dance
的时候硬整上去了,原理都不懂,也折腾了好久。
不过,这也就是学习的过程吧,从一个点再扩展到其他点,最后形成网。
折腾的不是很爽,最后还是靠降级实现目的的,不够优雅。不过也能用就行。
在 k8s 上跑 runner 集群这事,以后再说吧。