You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker构建中Gradle缓存丢失求助:如何保留RUN生成的缓存?

问题

我有一个自定义镜像,里面包含测试所需的所有Gradle依赖缓存。但最近发现新构建的镜像中缓存消失了,推测是公司CI管理员升级了Docker导致的。

我的Dockerfile内容如下:

FROM gradle:7.6-jdk11
COPY . .
RUN gradle test && ls -l .gradle/caches
RUN ls -l .gradle/caches

gradle test会在.gradle/caches目录生成缓存,但执行下一条RUN指令时,缓存却消失了。

构建日志如下:

...
Step 3/4 : RUN gradle test && ls -l .gradle/caches
 ---> Running in b19404b6a13f
...
Starting a Gradle Daemon
...
BUILD SUCCESSFUL
total 8
drwxr-xr-x  7 gradle gradle   98 Aug 28 08:24 .
drwxr-xrwx 12 gradle gradle  160 Aug 28 08:26 ..
drwxr-xr-x 12 gradle gradle 4096 Aug 28 08:26 7.6.4
drwxr-xr-x  6 gradle gradle  185 Aug 28 08:24 jars-9
drwxr-xr-x  2 gradle gradle   81 Aug 28 08:24 journal-1
drwxr-xr-x  4 gradle gradle   67 Aug 28 08:24 modules-2
-rw-r--r--  1 gradle gradle    4 Aug 28 08:23 tmp
drwxr-xr-x  2 gradle gradle    6 Aug 28 08:24 transforms-3
Removing intermediate container b19404b6a13f
 ---> 01b0d3b3a1a7
Step 4/4 : RUN ls -l .gradle/caches
 ---> Running in e0b1e4fe1b59
total 4
drwxr-xr-x 2 gradle gradle 17 Aug 28 08:26 .
drwxr-xrwx 5 gradle gradle 55 Aug 28 08:26 ..
-rw-r--r-- 1 gradle gradle  4 Aug 28 08:23 tmp
Removing intermediate container e0b1e4fe1b59
 ---> 659e47228e5d
Successfully built 659e47228e5d

最终镜像中没有.gradle/caches目录,请问如何防止Docker删除我的缓存?

Docker版本及信息:

docker version
Client: Docker Engine - Community
 Version:           24.0.6
 API version:       1.43
 Go version:        go1.20.7
 Git commit:        ed223bc
 Built:             Mon Sep  4 12:32:10 2023
 OS/Arch:           linux/amd64
 Context:           default
Server: Docker Engine - Community
 Engine:
  Version:          24.0.6
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.20.7
  Git commit:       1a79695
  Built:            Mon Sep  4 12:32:10 2023
  OS/Arch:          linux/amd64
  Experimental:     true
 containerd:
  Version:          1.6.24
  GitCommit:        61f9fd88f79f081d64d6fa3bb1a0dc71ec870523
 runc:
  Version:          1.1.9
  GitCommit:        v1.1.9-0-gccaecfc
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
[Pipeline] sh

docker info
Client: Docker Engine - Community
 Version:    24.0.6
 Context:    default
 Debug Mode: false

Server:
 Containers: 29
  Running: 20
  Paused: 0
  Stopped: 9
 Images: 48
 Server Version: 24.0.6
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 61f9fd88f79f081d64d6fa3bb1a0dc71ec870523
 runc version: v1.1.9-0-gccaecfc
 init version: de40ad0
 Security Options:
  seccomp
   Profile: /etc/docker/seccomp.json
 Kernel Version: 4.18.0-477.27.1.el8_8.x86_64
 Operating System: Red Hat Enterprise Linux 8.8 (Ootpa)
 OSType: linux
 Architecture: x86_64
 CPUs: 24
 Total Memory: 125.4GiB
 Name: platjenagent10.ci28302344.cloud.alfaintra.net
 ID: 1ca266ec-9d13-4088-ba7f-2000b2d45f15
 Docker Root Dir: /var/lib/docker
 Debug Mode: true
  File Descriptors: 173
  Goroutines: 178
  System Time: 2024-08-28T11:23:56.134551161+03:00
  EventsListeners: 0
 Experimental: true
解决方案

问题根源

核心问题在于:官方gradle镜像的默认Gradle用户缓存目录是/home/gradle/.gradle,而非项目目录下的.gradle。项目目录的.gradle是构建临时目录,Docker在清理中间容器时不会将其内容保留到最终镜像;同时Docker 24.x版本对中间层的清理逻辑更严格,放大了这个问题。

修复方案

  1. 切换到Gradle全局缓存目录
    修改Dockerfile,直接操作镜像默认的全局缓存目录,确保缓存被保留到最终镜像:

    FROM gradle:7.6-jdk11
    COPY . .
    # 先拉取依赖缓存,再执行测试
    RUN gradle dependencies && gradle test
    # 验证全局缓存存在
    RUN ls -l /home/gradle/.gradle/caches
    
  2. 利用Docker BuildKit缓存挂载(CI环境优先)
    启用Docker BuildKit后,通过挂载缓存目录,既能在构建时复用缓存提升速度,又能确保最终镜像保留缓存:

    # syntax=docker/dockerfile:1
    FROM gradle:7.6-jdk11
    COPY . .
    # 挂载Gradle全局缓存目录,构建时复用,最终镜像保留缓存
    RUN --mount=type=cache,target=/home/gradle/.gradle/caches \
        gradle test && ls -l /home/gradle/.gradle/caches
    RUN ls -l /home/gradle/.gradle/caches
    
  3. 合并RUN指令减少中间层
    将缓存生成和验证的命令合并到同一个RUN指令,避免中间容器清理导致的缓存丢失:

    FROM gradle:7.6-jdk11
    COPY . .
    RUN gradle test && ls -l /home/gradle/.gradle/caches && ls -l .gradle/caches
    

内容的提问来源于stack exchange,提问作者suit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:35:01