Use CircleCI Docker Layer Caching Orb to Cut Build Times
Learn how the circleci/docker orb’s Docker layer caching works, a working config example, and common pitfalls that can break your speed gains.
20 Sept 2026, 16:33 UTC

Why Docker Layer Caching Matters in CircleCI
When a pipeline spins up a new Docker container for each job, the container’s image layers are rebuilt from scratch unless a cache is reused. The circleci/docker orb provides restore_cache and save_cache steps that persist Docker’s layered filesystem between runs. A hit pulls the already‑downloaded dependency layers from S3, skipping the network round‑trip and drastically cutting image build time.
How the Orb Persists Layers
The orb writes a .docker/config.json file into the cache that contains the image’s layer digests. On the next run, restore_cache pulls the file and Docker re‑hydrates the layers locally. Because Docker layers are immutable, the same digest always resolves to the same content, ensuring deterministic builds.
Working Configuration Example
Below is a minimal .circleci/config.yml that caches a Node.js application’s node_modules and npm layers. The key is tied to the lock file so any dependency change invalidates the cache.
version: 2.1
orbs:
docker: circleci/docker@2.1.0
jobs:
build:
docker:
- image: cimg/node:20.10.0
steps:
- checkout
- restore_cache:
name: Restore npm cache
keys:
- npm-deps-{{ checksum "package-lock.json" }}
- npm-deps-
- run: npm ci
- save_cache:
name: Save npm cache
key: npm-deps-{{ checksum "package-lock.json" }}
paths:
- ~/.npm
- node_modules
- run: npm test
workflows:
version: 2
build_and_test:
jobs:
- build
Key points:
checksumgenerates a SHA‑1 of the lock file, so the key changes only when dependencies change.- Two restore keys allow a fallback to a stale cache if the exact key is missing.
- Only the necessary paths (
~/.npmandnode_modules) are cached to keep the cache small.
Verifying Cache Hits and Misses
After a job runs, open the CircleCI UI and click Artifacts. The orb writes a file named cache-hit.txt inside the cache that contains hit or miss. Inspect this file to confirm whether the cache was used. Additionally, the job logs include a line like Cache hit: npm-deps-… when a hit occurs.
To validate the YAML and ensure the orb reference is correct, run:
circleci config validate
Running circleci lint in your pipeline can surface mis‑typed cache keys before they cause a miss.
Common Mistakes and Limitations
- Cache staleness: If you forget to include the lock file in the key, a dependency update will not invalidate the cache, leading to failed builds.
- Overly broad paths: Caching entire
node_modulesdirectories for monorepos can inflate cache size and transfer time, offsetting the benefit. - Orb version drift: Pinning the orb (e.g.,
circleci/docker@2.1.0) prevents breaking changes. Updating the orb without reviewing the changelog may introduce new key requirements. - Cache size limits: CircleCI’s default cache storage is 2 GB. Exceeding this triggers automatic eviction, which can cause a miss on subsequent runs.
- Parallelism interference: When jobs run in parallel, they share the same cache. If two jobs write to the same cached path concurrently, one may overwrite the other’s data.
Practical Checklist Before You Commit
- Pin the orb to a specific version and run
circleci config validate. - Define cache keys that include the exact dependency files (e.g.,
package-lock.json,Gemfile.lock). - Limit cached paths to the minimal set needed for the next job step.
- Add
circleci lintto the pipeline to catch key syntax errors. - After a successful run, check the Build Artifacts for
cache-hit.txtand confirm the hit status. - Monitor cache size in the CircleCI UI; if it’s near 2 GB, consider pruning or splitting the cache.
By following these guidelines, you can reliably leverage Docker layer caching to shave minutes off your CI pipeline, reduce bandwidth usage, and maintain deterministic builds.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.