Intro
The Docker build cache is one of the most powerful tools for keeping image builds fast and CI/CD pipelines efficient. It stores intermediate layers and reuses them whenever the corresponding instructions and build context have not changed. When the cache works well, builds that took minutes can drop to seconds. But when the cache behaves unexpectedly, developers face slow builds, bloated disk usage, and inconsistent images that are hard to debug.
Monitoring and alerting on build cache performance helps teams detect these issues early, reduce developer friction, and keep pipelines reliable. Without visibility, a cache problem can silently degrade builds for days, wasting compute and delaying releases.
This guide explains what to monitor in Docker Build Cache, the key metrics to track, how to set up alert rules and dashboards, and what to do during an incident. Every major step includes concrete commands, configuration snippets, or worked examples so you can implement monitoring in your own environment.
Version and Environment Inventory
Before implementing cache monitoring, establish your environment and prerequisites. Different Docker and BuildKit versions expose different metrics and caching behavior, so start by confirming what you are running.
Docker and BuildKit Versions
Docker build cache behavior depends on the Docker Engine version and the build backend. BuildKit, the default builder for Docker 23.0 and later, provides advanced caching and better performance. Check your Docker version with:
docker version --format '{{.Server.Version}}'
Example output:
24.0.5
Verify that BuildKit is available and check its version:
docker buildx version
Expected output includes the buildx version:
github.com/docker/buildx v0.11.2
If you are on an older Docker version, consider upgrading. Newer releases include improved cache management, better BuildKit integration, and more reliable metrics endpoints.
Environment Topology
Cache is stored locally on each build node. In a typical development setup, that means the developer's laptop or a CI runner. In larger setups, teams often use a shared remote cache, such as a container registry with cache support or a distributed cache like BuildKit's registry cache. Remote caches let multiple machines reuse the same layers, which is critical for horizontally scaled CI runners.
For this guide, we assume a single-node local environment with Docker Engine and BuildKit enabled. The examples are easy to adapt for remote caches: you would simply add cache import and export flags to your build commands.
Prerequisites
- Docker Engine 20.10 or later (for BuildKit support).
- Command-line access to the build environment.
- Basic knowledge of Prometheus, Grafana, or your monitoring stack.
- Optional: Node Exporter or cAdvisor for host-level metrics such as disk usage.
Safe Configuration Path
Start with a narrow, measurable pilot. Monitor local cache metrics on one build node before expanding to remote or distributed caches. This reduces risk and lets you tune alerts without affecting the whole fleet.
Enabling BuildKit Metrics
BuildKit exposes Prometheus metrics via an HTTP endpoint when run as a standalone daemon with the right flags. Docker's integrated BuildKit does not expose metrics directly, but you can run a separate BuildKit daemon for monitoring and testing:
sudo buildkitd --addr unix:///run/buildkit/buildkitd.sock --debug --addr tcp://0.0.0.0:1234
Then access metrics at http://localhost:1234/metrics. This is ideal for understanding available metrics before integrating with your production build setup.
For normal Docker builds using the default BuildKit, you can still get cache visibility from build logs. Set the environment variable BUILDKIT_PROGRESS=plain to see cache status in log output, though it is not time-series data.
Instrumenting Build Commands
Instead of direct metrics, you can add monitoring around your build commands. Use docker buildx build with the --progress=plain flag to capture cache hits and misses in the log output:
docker buildx build --progress=plain -t myapp:latest . 2>&1 | tee build.log
Then parse the log for lines that indicate cache results. A cache hit appears like this:
#12 [stage-1 2/4] COPY --from=builder /app /app
#12 CACHED
A cache miss looks like this:
#12 [stage-1 2/4] COPY --from=builder /app /app
#12 DONE 0.2s
Automate this parsing with a script or log aggregation tool such as Loki or ELK. You can then create metrics and alerts based on cache hit ratio derived from logs.
Setting Up Prometheus and Grafana
If you run standalone BuildKit, you can scrape its metrics with Prometheus. Add a scrape config like this:
scrape_configs:
- job_name: 'buildkit'
static_configs:
- targets: ['localhost:1234']
Then create a Grafana dashboard to visualize cache-related metrics. The specific metrics and dashboard panels are covered in the next section.
Verification and Diagnostics
Once monitoring is in place, verify that it captures the expected data and behaves correctly. Start by checking that the metrics endpoint responds and that Prometheus is scraping it. Then explore the key metrics and how to turn them into dashboards and alerts.
Key Metrics to Monitor
BuildKit exposes a variety of metrics. The most relevant for cache monitoring are:
| Metric | Type | Description |
|---|---|---|
buildkit_cache_hits_total | Counter | Number of cache hits |
buildkit_cache_misses_total | Counter | Number of cache misses |
buildkit_cache_imports_total | Counter | Number of cache imports |
buildkit_cache_exports_total | Counter | Number of cache exports |
buildkit_cache_usage_bytes | Gauge | Current cache size in bytes |
Metric names may differ slightly depending on BuildKit version. Always check the /metrics endpoint for the exact names in your environment. You can query it manually with:
curl -s http://localhost:1234/metrics | grep buildkit_cache
Expected output (truncated):
# HELP buildkit_cache_hits_total Total number of cache hits
# TYPE buildkit_cache_hits_total counter
buildkit_cache_hits_total 42
# HELP buildkit_cache_misses_total Total number of cache misses
# TYPE buildkit_cache_misses_total counter
buildkit_cache_misses_total 7
Calculating Cache Hit Ratio
A useful derived metric is the cache hit ratio, which tells you what fraction of cache lookups resulted in hits. The formula is:
cache_hit_ratio = buildkit_cache_hits_total / (buildkit_cache_hits_total + buildkit_cache_misses_total)
In Prometheus, you can use a PromQL query in Grafana:
sum(rate(buildkit_cache_hits_total[5m])) / (sum(rate(buildkit_cache_hits_total[5m])) + sum(rate(buildkit_cache_misses_total[5m])))
This expression gives the proportion of cache hits over the last 5 minutes. A healthy cache typically has a hit ratio above 0.8, but this can vary by workload.
Dashboard Example
Create a Grafana dashboard with these panels:
- Cache Hit Ratio - A graph showing the ratio over time. Use the PromQL expression above.
- Cache Hits vs Misses - A stacked graph of
rate(buildkit_cache_hits_total[5m])andrate(buildkit_cache_misses_total[5m])to see the volume of each. - Cache Size - A graph of
buildkit_cache_usage_bytesto track disk usage. - Cache Imports/Exports - Graphs of import and export rates to monitor remote cache traffic.
Set a threshold on the hit ratio panel to highlight when the ratio drops below 0.8. This makes it easy to spot problems at a glance.
Log-Based Verification
If you are using log parsing, verify that your parser correctly identifies hits and misses. For example, a simple AWK script can count CACHED lines in a build log:
grep -c 'CACHED' build.log
Expected output is the number of cached steps. You can also extract misses by counting DONE lines that are not CACHED, but that requires a bit more logic. A more robust approach is to use a tool like Loki to aggregate log lines and calculate ratios over time.
Failure Modes and Recovery
Monitoring itself can fail or produce false alerts. Be prepared to handle common issues with cache and metrics collection.
Common Failure Modes
- Cache Invalidation Due to Dockerfile Changes: Changing an instruction in the Dockerfile invalidates all subsequent layers, causing cache misses. This is expected and can trigger alerts if thresholds are too sensitive.
- Disk Space Exhaustion: The build cache can grow large and fill the disk, causing build failures. Monitor disk usage and set a maximum cache size using
--max-cache-sizein BuildKit. - Corrupted Cache: Occasionally, the cache can become corrupted, causing unexpected misses or build errors. Clearing the cache with
docker builder pruneresolves this. - Network Issues with Remote Cache: If using a remote cache, network latency or unavailability can cause cache imports and exports to fail, appearing as cache misses.
- Metric Collection Failure: The metrics endpoint may be unreachable due to network misconfiguration or BuildKit not exposing it. This results in no data and missed alerts.
Alert Rules
Define alert rules to detect issues without being overly noisy. Example Prometheus alert rules:
groups:
- name: docker_build_cache
rules:
- alert: LowCacheHitRatio
expr: (sum(rate(buildkit_cache_hits_total[5m])) / (sum(rate(buildkit_cache_hits_total[5m])) + sum(rate(buildkit_cache_misses_total[5m])))) < 0.6
for: 10m
labels:
severity: warning
annotations:
summary: "Build cache hit ratio is low"
description: "Cache hit ratio has been below 0.6 for 10 minutes."
- alert: CacheUsageHigh
expr: buildkit_cache_usage_bytes > 50e9 # 50 GB, adjust as needed
for: 5m
labels:
severity: warning
annotations:
summary: "Build cache usage is high"
description: "Cache size exceeds 50 GB."
Adjust thresholds based on your baseline. Some teams prefer to alert only when the hit ratio stays low for a longer period to avoid noise from legitimate changes.
Recovery and Rollback
When an alert fires, follow these steps:
- Investigate cache hit ratio: Check recent Dockerfile changes and build context modifications. If the change is legitimate, adjust thresholds or temporarily silence the alert.
- Free disk space: Run
docker builder prune --filter 'until=24h'to remove unused cache. For a full clean, usedocker builder prune -awith caution. - Fix remote cache connectivity: Ensure network access and credentials are valid. Test with a simple build that uses the remote cache.
- Restart BuildKit if the metrics endpoint is down.
- Rollback monitoring changes: If a new alert rule causes noise, revert it immediately and iterate on thresholds.
Incident Response Workflow
Create a runbook for cache-related incidents. Include:
- Symptom identification: slow builds, high cache misses, disk full.
- Immediate mitigation: prune cache, disable cache temporarily with
--no-cache, or fall back to local cache. - Root cause analysis: examine Dockerfile changes, build context size, remote cache performance, and recent environment changes.
- Post-incident review: update thresholds, improve monitoring coverage, and document lessons learned.
Assign a single accountable owner for cache incident response. For example, the platform engineer on call owns mitigation and initial diagnosis. Review the runbook quarterly or after every major incident.
Common Pitfalls and How to Avoid Them
Even with monitoring in place, teams make mistakes that reduce cache efficiency or create alert fatigue. Here are the most common pitfalls and how to avoid or recover from them.
Pitfall 1: Ignoring Build Context Size
Why it happens: Developers add large files or directories to the build context without realizing it. A huge context can slow down builds and cause unnecessary cache misses because the context hash changes.
How to avoid: Use a .dockerignore file to exclude unnecessary files from the build context. Review it regularly. A good .dockerignore can dramatically improve cache performance. For example:
.git
*.md
node_modules
How to recover: If you discover a bloated context, update .dockerignore and prune old cache entries with docker builder prune.
Pitfall 2: Over-Alerting on Cache Hit Ratio
Why it happens: Teams set alert thresholds too high or with too short a for duration. Legitimate Dockerfile changes cause temporary misses and trigger noisy alerts.
How to avoid: Set realistic thresholds based on historical data. Use a longer for period, such as 15 minutes, to avoid transient dips. Alert on trends, not single data points.
How to recover: Adjust thresholds and test with a maintenance window. Silence alerts during planned changes if necessary.
Pitfall 3: Not Monitoring Disk Usage
Why it happens: Cache size is not tracked, or alerts are only on hit ratio. The disk fills up and builds fail.
How to avoid: Monitor host disk usage with Node Exporter or cAdvisor. Set a maximum cache size in BuildKit using --max-cache-size and alert when usage exceeds a safe threshold (e.g., 80 percent of disk).
How to recover: Immediately prune the cache with docker builder prune --filter 'until=24h'. Investigate what caused the growth, such as a change in base images or an increase in parallel builds.
Pitfall 4: Using Remote Cache Without Monitoring Connectivity
Why it happens: Teams adopt a remote cache for speed but do not monitor cache import and export success. Network issues silently reduce cache effectiveness.
How to avoid: Monitor buildkit_cache_imports_total and buildkit_cache_exports_total for failures. If possible, use BuildKit logs to detect connection errors. Set up alerts for sudden drops in imports or exports.
How to recover: Check network connectivity and credentials. Test with a simple build that uses the remote cache. If the remote cache is unavailable, temporarily fall back to local cache to avoid blocking builds.
Pitfall 5: Not Validating Metrics Collection
Why it happens: Metrics endpoint is misconfigured or BuildKit is not running. Dashboards show no data, and alerts never fire.
How to avoid: Set up a Prometheus alert for up == 0 on the BuildKit job. This ensures you are notified if the endpoint goes down. Also, regularly check dashboards manually during the first week of setup.
How to recover: Diagnose why the endpoint is unreachable. Check BuildKit logs, network access, and Prometheus scrape config. Restart BuildKit if necessary.
Operations Checklist
Use this checklist for day-to-day operations and periodic reviews. Assign a single owner for each major item to ensure accountability.
Daily/Weekly Checks
- [ ] Monitor cache hit ratio dashboard - Owner: DevOps engineer on rotation. Investigate if below 0.8 for more than 30 minutes.
- [ ] Check disk space on build nodes - Owner: System administrator. Ensure cache size is within limits; trigger prune if above 80 percent disk usage.
- [ ] Review alerts - Owner: On-call engineer. Acknowledge and resolve any triggered alerts.
- [ ] Verify metrics collection - Owner: Platform engineer. Check Prometheus for gaps in data; confirm BuildKit endpoint is up.
Monthly Review
- [ ] Evaluate cache effectiveness - Owner: Build infrastructure lead. Are hit ratios improving or degrading? Review trends and identify causes.
- [ ] Update alert thresholds - Owner: Platform engineer. Based on the last month's data, adjust thresholds to reduce noise and catch real issues.
- [ ] Clean up old cache - Owner: System administrator. Run
docker builder prune --filter 'until=30d'during a maintenance window. - [ ] Test recovery procedures - Owner: DevOps engineer. Simulate a failure (e.g., fill the disk) and practice the incident response runbook.
- [ ] Review Dockerfile optimizations - Owner: Application team lead. Look for opportunities to improve cache reusability, such as reordering layers or using multi-stage builds.
Quarterly Audit
- [ ] Audit cache configuration - Owner: Security engineer. Review remote cache endpoints, credentials, and size limits. Rotate credentials if needed.
- [ ] Assess monitoring coverage - Owner: Platform engineer. Ensure all build nodes are scraped and dashboards reflect all environments.
- [ ] Update dashboards - Owner: DevOps engineer. Add new metrics or visualizations based on team feedback.
- [ ] Train new team members - Owner: Team lead. Run through the incident runbook and monitoring dashboards with any new engineers.
Each checklist item has a single owner and a defined review frequency. This prevents the common problem of "everyone is responsible, so no one is."
Conclusion
Monitoring and alerting for Docker Build Cache is essential for maintaining fast, efficient builds. Start with a narrow pilot: enable metrics on a single build node, set up basic dashboards, and create a few alert rules. Use the version inventory and safe configuration steps in this guide to implement monitoring without disrupting existing workflows. Verify that metrics are collected and visualized correctly, and prepare for common failure modes with a clear recovery plan.
By following the operations checklist, you can ensure ongoing cache health and quickly detect and resolve issues. For next steps, consider expanding monitoring to remote caches, integrating with CI/CD pipelines for historical analysis, and exploring advanced BuildKit features like cache mounts.
All examples and hypothetical numbers are constructed for demonstration; adjust thresholds and configurations to fit your environment. The concrete commands and configurations throughout this guide give you a starting point that you can adapt to your own infrastructure.