Caching Maven and Gradle Dependencies in a DevContainer
JVM projects pull large dependency trees, and re-downloading them every rebuild is slow. This page caches the Maven ~/.m2 repository or the Gradle cache on a named volume, so a rebuild reuses downloaded artifacts and builds stay fast.
Prerequisites
You need a Java devcontainer using Maven or Gradle.
- A Java Feature pinned to a JDK.
- Maven or Gradle (ideally via the wrapper).
- A named volume for the dependency store.
Step-by-Step Implementation
- Mount the dependency store on a volume (Gradle shown).
{
"mounts": ["source=devcontainer-gradle-cache,target=/home/vscode/.gradle,type=volume"],
"remoteUser": "vscode"
}
- Or for Maven, cache ~/.m2.
{ "mounts": ["source=devcontainer-m2,target=/home/vscode/.m2,type=volume"] }
- Warm the cache on create.
{ "postCreateCommand": "./gradlew --no-daemon dependencies" }
- Verify a rebuild reuses the store.
./gradlew --no-daemon build --offline # succeeds from cache
Common Pitfalls
Slow JVM builds come from an uncached store or missing wrapper.
| Symptom | Root Cause | Remediation |
|---|---|---|
| Dependencies re-download each build | Store not on a volume | Mount ~/.m2 or ~/.gradle on a volume |
| Tool version varies | Not using the wrapper | Run via mvnw/gradlew |
| Cache permission errors | Volume owned by root | chown the store to the remote user |
| Offline build fails | Cache not warmed | Warm it in postCreateCommand |
Conclusion
Cache the dependency store on a named volume — ~/.m2 for Maven or ~/.gradle for Gradle — and run through the wrapper so the build-tool version is pinned. A rebuild then reuses downloaded artifacts, and JVM dependency trees stop slowing every build.
FAQ
Which directory should I cache, Maven or Gradle?
Cache the one your build uses: ~/.m2/repository for Maven, or ~/.gradle for Gradle. Mount it on a named volume so downloaded artifacts persist across rebuilds. If you use both tools, cache both directories.
Does caching change build reproducibility?
No, as long as you build through the wrapper (mvnw/gradlew), which pins the tool version, and your build files pin dependency versions. The cache only holds artifacts your build already resolved, so it speeds builds without altering results.
Why do I get permission errors on the cache volume?
The volume is owned by root but your remoteUser isn't. chown the cache directory to the remote user (in a hook or the Dockerfile), and the non-root build can read and write it.
Related
- Up to Java & JVM DevContainer Configuration — the overview of JVM setup.
- Configuring the JDK Version in a DevContainer — pinning the JDK.
- Debugging Java in a DevContainer — attaching the debugger.