Docker Build Context and .dockerignore
What the trailing dot in docker build actually sends, why a stray 3MB file made the image 6MB bigger, and how one .dockerignore file cut the transfer from 3.00MB to 138B. Measured both ways.
Dockerfiles and Builds Guide 16 of 46 Intermediate
- OSUbuntu 26.04 LTS (resolute)
- Docker Engine29.7.2
- Shellbash
- Architectureamd64
- TimeAbout 12 min
- Reviewed20 August 2026
Tested on the versions above. Transfer sizes depend on your own files. Step numbers and timings vary per run. Match the shape of the output, not the exact strings.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| DOCKER01 | 192.168.0.21 | Ubuntu 26.04 LTS | Docker Host | 2 Core | 4 GB | 50 GB |
Before you start
- You can build an image from a Dockerfile - guide 14.
- A writable working directory. This guide uses /tmp/cg-ctx.
-
The dot is an argument, not punctuation
In
docker build -t name .the final dot is the build context: the directory handed to the builder. Instructions such as COPY can only read files from inside it, which is why copying something from outside the context is impossible rather than merely awkward.bash ls -la /tmp/cg-ctxtotal 3076drwxrwxr-x 3 sysadmin sysadmin 100 Aug 22 09:17 .drwxrwxrwt 13 root root 260 Aug 22 09:17 ..-rw-rw-r-- 1 sysadmin sysadmin 64 Aug 22 09:17 Dockerfile-rw-rw-r-- 1 sysadmin sysadmin 3145728 Aug 22 09:17 bigfile.bindrwxrwxr-x 2 sysadmin sysadmin 60 Aug 22 09:17 srcExpected resultA directory holding both what the build needs and what it does not.
Success conditionYou can see at least one file the image has no use for. Real projects have many: .git, node_modules, test fixtures, local databases.
-
Measure what actually transfers
BuildKit reports the context transfer as a numbered step. This is worth watching, because the common advice that "the whole directory is uploaded" is only true when your instructions reference the whole directory. With
COPY . .they do - and the full three megabytes moves.bash Example session docker build --no-cache -t cg-ctx:nodockerignore .#3 transferring context: 2B done#6 transferring context: 3.00MB doneExpected resultTwo transfer lines - the small one is the .dockerignore lookup, the large one is the context itself.
Success conditionYou can see the transferred size. Note it is reported per build, so this cost is paid every time.
-
Add a .dockerignore
The syntax is close to .gitignore: one pattern per line, matched against paths relative to the context root. It is read before anything transfers, which is why it reduces the transfer rather than merely the image.
bash printf "bigfile.bin\n*.md\n" > .dockerignorecat .dockerignorebigfile.bin*.mdExpected resultThe two patterns.
Success conditionThe file is named exactly
.dockerignoreand sits at the context root - not next to the Dockerfile if those differ. -
Measure again
Same Dockerfile, same command, same
--no-cache. The only change is the ignore file, and the transfer drops by four orders of magnitude.bash Example session docker build --no-cache -t cg-ctx:withdockerignore .#3 transferring context: 57B done#6 transferring context: 138B doneExpected resultThe context transfer falls from 3.00MB to 138B.
Success conditionA dramatically smaller transfer. If it did not change, the pattern is not matching - patterns are relative to the context root, so a leading slash or a wrong directory prefix will silently match nothing.
-
The image shrank too
Because
COPY . .copied the excluded file into the image as well, ignoring it removes it from both the transfer and the result. Six megabytes of image for a file nothing reads.bash Example session docker images --filter reference=cg-ctx --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}"REPOSITORY:TAG SIZEcg-ctx:withdockerignore 12.8MBcg-ctx:nodockerignore 18.8MBExpected resultA 6MB difference from one ignore rule.
Success conditionThe ignored build is smaller. On a real project with node_modules or .git the difference is usually far larger than this.
-
Clean up
Remove both tagged images and the working directory.
bash # removes only what this guide builtdocker rmi cg-ctx:nodockerignore cg-ctx:withdockerignorerm -rf /tmp/cg-ctx# doneExpected resultUntagged lines for both images.
Success condition
docker images --filter reference=cg-ctxreturns nothing.
Troubleshooting
.dockerignore appears to have no effect
Why: It is in the wrong place or the pattern does not match. The file must be at the root of the build context, and patterns are relative to that root - not to the Dockerfile's location if you passed -f pointing elsewhere.
Fix:Confirm the file's location relative to the context argument, then re-measure the transferring context line rather than guessing.
bash ls -la .dockerignoredocker build --no-cache -t tmp . 2>&1 | grep "transferring context"A secret ended up inside the image
Why: COPY . . copies everything not ignored, including .env files, keys and credentials. Deleting them in a later instruction does not help - the earlier layer still contains them and anyone with the image can read it.
Fix:Exclude them in .dockerignore so they never enter the context, and copy specific paths rather than the whole directory. Rotate anything that was already built into a published image.
bash # a deleted file is still in the layer that added itdocker history --no-trunc IMAGE | grep -i copyThe build is slow before any instruction runs
Why: A large context is being transferred. Building from a home directory or a repository root with build artifacts in it is the usual cause.
Fix:Build from a dedicated directory, or add an ignore file. The transferring context line tells you how much is moving.
bash du -sh .docker build --no-cache -t tmp . 2>&1 | grep "transferring context"