The Build Context is the folder Docker sends to the build engine when we run docker build.
If you write docker build -t mi-app ., press Enter, and your terminal freezes with this message:
load build definition from Dockerfile load .dockerignore load build context Transferring context: 890.50MB 25.3s
You wait… wait… and wonder: Why does it take so long if my Dockerfile only has 4 lines?
The answer lies in how Docker’s architecture works. Today we’ll look at the concept called Build Context, and also how to remove files from it using the .dockerignore file.
Understanding the Architecture: Client vs Daemon
To understand the problem, we need to remember what we saw at the beginning of the course: Docker is Client-Server.
- The Client (CLI): This is your terminal, where you type commands.
- The Daemon (Engine): This is the server that creates images and containers.
When you run:
docker build -t mi-imagen .
That final period . is not decorative. It defines the context. You are telling the client: “package everything in this directory and send it to the daemon so it can work with it.”
The Daemon does not have access to your hard drive. For it to execute instructions like COPY . ., the Client first has to create a .tar (a zip) of the entire folder and send it over the network (or socket) to the Daemon.
The typical mistake is running docker build . from your user’s root folder (C:\Users\Luis).
Docker will try to package your Documents, Downloads, Videos… And it will freeze half your PC trying to send all that to the Daemon.
The Solution: .dockerignore
Just like in Git we have the .gitignore file to avoid uploading junk to the repository, in Docker we have the .dockerignore.
It is a plain text file that must be in the same folder as the Dockerfile. In it, we list the files and folders that the Client must ignore when preparing the context.
How does it work?
When you run docker build:
- The Client looks for the
.dockerignorefile. - It filters the files in the folder according to that list.
- It packages only what is left and sends it to the Daemon.
The result: A context that goes from 1GB to 200KB
Syntax
The syntax is very similar to .gitignore.
# Ignore local dependencies (they will be installed inside the image)
node_modules
dist
build
# Ignore version control folder
.git
.gitignore
# Ignore environment files with secret keys
.env
*.pem
# Ignore operating system files
.DS_Store
Thumbs.db
# Ignore logs and temporary files
*.log
tmp/
Practical Example
Let’s simulate it so you can see the real difference.
Create a folder. Create a large file (simulating junk).
# On Linux/Mac (creates a 100MB file)
dd if=/dev/zero of=large-file bs=1M count=100
Create a simple Dockerfile:
FROM alpine
COPY . /app
Run the build:
time docker build -t test-dirty .
Observe the message Transferring context: 105MB. It will take a few seconds.
Create a .dockerignore file and add:
large-file
Run the build again:
time docker build -t test-clean .
Message: Transferring context: 2KB. Instant.
Beyond Speed: Security
Using .dockerignore is not just about performance. It is a matter of security.
If you do COPY . . in your Dockerfile and haven’t ignored sensitive files, you will be putting into the final image:
.envfiles with production passwords..gitfolders containing the entire change history (and perhaps keys deleted in the past).- Private SSH keys.
If you then upload that image to Docker Hub, anyone can download it and extract your secrets, even if they are not visible at a glance in the application.
Always add .env and .git to your .dockerignore even before you start writing the Dockerfile.
