Cache Volumes
One of Dagger's most powerful features is its ability to cache data across pipeline runs.
Dagger caches two types of data:
- Layers: This refers to build instructions and the results of some API calls. This cache is implemented by Buildkit.
- Volumes: This refers to the contents of a Dagger filesystem volume and is persisted across Dagger Engine sessions. This cache is maintained locally and, where applicable, replicated to Dagger Cloud. It is implemented by Dagger (distinct from Buildkit).
Volume caching is especially useful when dealing with package managers such as npm
, maven
, pip
and similar. For these tools to cache properly, they need their own cache data (usually a directory) to be persisted between runs. By using a cache volume for this data, Dagger can reuse the cached contents across Dagger Function runs and reduce execution time.
Cache volumes must be explicitly defined and used in your Dagger Function. Here is an example:
- Go
- Python
- TypeScript
package main
import "dagger/my-module/internal/dagger"
type MyModule struct{}
// Build an application using cached dependencies
func (m *MyModule) Build(
// Source code location
source *dagger.Directory,
) *dagger.Container {
return dag.Container().
From("golang:1.21").
WithDirectory("/src", source).
WithWorkdir("/src").
WithMountedCache("/go/pkg/mod", dag.CacheVolume("go-mod-121")).
WithEnvVariable("GOMODCACHE", "/go/pkg/mod").
WithMountedCache("/go/build-cache", dag.CacheVolume("go-build-121")).
WithEnvVariable("GOCACHE", "/go/build-cache").
WithExec([]string{"go", "build"})
}
from typing import Annotated
import dagger
from dagger import Doc, dag, function, object_type
@object_type
class MyModule:
@function
def build(
self, source: Annotated[dagger.Directory, Doc("Source code location")]
) -> dagger.Container:
"""Build an application using cached dependencies"""
return (
dag.container()
.from_("python:3.11")
.with_directory("/src", source)
.with_workdir("/src")
.with_mounted_cache("/root/.cache/pip", dag.cache_volume("python-311"))
.with_exec(["pip", "install", "-r", "requirements.txt"])
)
import { dag, Container, Directory, object, func } from "@dagger.io/dagger"
@object()
class MyModule {
/**
* Build an application using cached dependencies
*/
@func()
build(
/**
* Source code location
*/
source: Directory,
): Container {
return dag
.container()
.from("node:21")
.withDirectory("/src", source)
.withWorkdir("/src")
.withMountedCache(
"/src/node_modules",
dag.cacheVolume("node-21-myapp-myenv"),
)
.withMountedCache("/root/.npm", dag.cacheVolume("node-21"))
.withExec(["npm", "install"])
}
}