DEV Community

Cover image for Docker build cache: the .dockerignore gotcha
Harshit Luthra
Harshit Luthra

Posted on Edited on Originally published at harshit.cloud

Docker build cache: the .dockerignore gotcha

Originally published at harshit.cloud on 2024-12-05.


Spent 2 hours debugging why my Docker builds were slow despite using multi-stage builds and proper layer ordering.

the issue

Every single build was invalidating the cache at the COPY . . step, even when I hadn't changed any code.

the culprit

My editor was creating .swp files and updating file timestamps. Docker saw these changes and invalidated the cache.

the fix

Add a proper .dockerignore:

.git
.gitignore
README.md
.env*
node_modules
npm-debug.log
.next
.vscode
*.swp
*.swo
.DS_Store
Enter fullscreen mode Exit fullscreen mode

Build time went from 5 minutes to 30 seconds.

how to tell it worked

The first lines of build output say how much context was sent to the daemon, and that number is the whole diagnosis:

 => [internal] load .dockerignore                             0.0s
 => => transferring context: 2.31kB                           0.0s
Enter fullscreen mode Exit fullscreen mode

Kilobytes is healthy. Hundreds of megabytes means the file is missing, or the pattern you wrote does not match what you think it matches. .dockerignore uses Go's filepath.Match rules, not .gitignore rules, and the difference bites in one specific place: **/ for recursive matching is supported, but a bare directory name like node_modules only matches at the root. Nested copies need **/node_modules.

Treat .dockerignore like .gitignore. Be aggressive about what you exclude.

The longer version of this, including why the same Dockerfile caches on your laptop and rebuilds everything on a CI runner, is in why your Docker build caches locally and never in CI. More under Docker and containers.

Top comments (0)