Why builds are fast the second time
Run docker build twice in a row and the second run finishes instantly with CACHED next to every step. Docker reuses the layer from last time when it can prove nothing changed.
The cache rule, worth memorizing:
- An instruction's layer is reused if the instruction text is unchanged and any files it copies are unchanged
- The moment one step misses the cache, every step after it rebuilds too, because each layer builds on the previous one
Rule 2 is why order matters. Put the things that change rarely (dependencies) near the top, and the things that change constantly (your code) near the bottom.
The classic pattern, explained
Now the Dockerfile from lesson 3-1 makes full sense:
COPY requirements.txt . RUN pip install -r requirements.txt COPY . .
Why copy requirements.txt alone first, then everything later? Because of what changes between builds:
- You edit
server.pyand rebuild.requirements.txtis unchanged, so the COPY and the wholepip installlayer are cache hits. Only the finalCOPY . .reruns. Build time: about a second - If instead the Dockerfile said
COPY . .beforepip install, any code edit would invalidate that copy, and rule 2 would force pip to reinstall every package on every build. Build time: minutes, every time
Same image either way. Wildly different feedback loop.
Code exercise · bash
Run this cache oracle. It plays the role of Docker deciding where the rebuild starts, based on which file changed. server.py changed here, so the expensive pip install layer is safely reused. Change the variable to requirements.txt in your head and predict the other branch.
Quiz
Your Dockerfile is: FROM, COPY requirements.txt, RUN pip install, COPY . ., CMD. You edit only server.py and rebuild. Which steps rerun?
.dockerignore
COPY . . copies the whole build context, which can drag in junk: the .git history, node_modules/, virtualenvs, .env files with secrets. That bloats the image, slows the build, and can leak credentials.
The fix is a .dockerignore file next to your Dockerfile, same idea as the .gitignore you know from the git course:
.git node_modules __pycache__ .env *.log
Anything listed is excluded from the build context, so COPY . . never sees it. Every real project should have one, and .env belongs in it for the same reason it belongs in .gitignore. Secrets get a proper home in lesson 8-2.
Problem
What file, placed next to your Dockerfile, lists paths that should be excluded from the build context?