.dockerignore Explained: Faster Builds, Smaller Images, No Leaked Secrets
A .dockerignore file keeps files out of the Docker build context: node_modules, .git, .env files, build output. Why that makes builds faster and images smaller, how it prevents secrets ending up in images, the syntax and negation rules, a ready-to-use template, and how to check what's being sent.
When you run docker build ., Docker first packages up the folder you pointed it at — the build context — and sends it to the builder. Every COPY . . in your Dockerfile copies from that context.
A .dockerignore file lists what to leave out. Without one, Docker sends everything: your node_modules, your whole .git history, and your .env file full of secrets. (Dockerfile Explained)
Why it matters
1. Secrets end up in images. COPY . . with no .dockerignore copies .env, private keys and credentials files into the image. Anyone who can pull the image can read them — even if a later step deletes the file, it's still in an earlier layer. (Docker Image Layers and OverlayFS)
2. Builds are slow. Sending a 500 MB node_modules or a large .git folder to the builder on every build wastes time before anything happens.
3. Caching breaks. If irrelevant files (logs, editor settings, git metadata) are in the context, they change constantly, and any COPY . . layer gets rebuilt for no reason.
4. Images are bigger and less reproducible. Your local node_modules (built for your Mac) can overwrite the one installed inside the Linux image. (Exec Format Error)
A good starting template (Node.js)
# .dockerignore
.git
.gitignore
node_modules
npm-debug.log*
.next
dist
build
coverage
.env
.env.*
!.env.example
*.pem
*.key
.DS_Store
.vscode
.idea
Dockerfile*
docker-compose*.yml
README.md
For Python, swap in __pycache__, *.pyc, .venv, .pytest_cache and .mypy_cache.
Syntax
- One pattern per line, relative to the build context root.
*matches anything except/;**matches any number of directories (**/*.log).#starts a comment.!re-includes something an earlier line excluded — order matters, the last matching line wins:
.env*
!.env.example
- Unlike
.gitignore, a pattern likenode_modulesonly matches at the context root. Use**/node_modulesto catch nested ones in a monorepo.
Check what's actually being sent
The build output shows the context size:
=> [internal] load build context
=> => transferring context: 2.14kB
Kilobytes or a few megabytes is healthy. Hundreds of megabytes means something big isn't ignored.
To inspect the final image for files that shouldn't be there:
docker run --rm -it myapp:latest sh -c "ls -la /app; ls -la /app/.env* 2>/dev/null"
It doesn't replace good Dockerfile habits
- Copy dependency manifests first, install, then copy source — so dependency layers stay cached:
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
- Use multi-stage builds, so build tools and source don't end up in the runtime image. (Production Dockerfile for Node, Reduce Docker Image Size)
- Pass secrets at runtime (environment variables) or with BuildKit secret mounts at build time — never
COPYthem. (Secrets Management Beyond .env Files)
If a secret already went into an image
Assume it's exposed: rotate the secret, rebuild without it, and delete the old image tags from your registry. (Leaked API Key: What to Do)
The summary
.dockerignorekeeps files out of the build context.- Always ignore
.git,node_modules, build output and every.envfile. - Check the "transferring context" size, and never rely on deleting secrets in a later layer.
EasySpawn keeps your app's secrets in server-side environment variables rather than in images or repos, and Claude Code can audit your Dockerfile and .dockerignore for leaks. See how it works or join the waitlist.
Related: What Is Docker? · Docker Image vs Container · .gitignore Explained · Docker Commands Cheat Sheet
Keep reading
How to Self-Host n8n: Docker, Postgres, HTTPS and Backups
A production-minded guide to self-hosting n8n: Docker Compose with Postgres instead of SQLite, the environment variables that matter (encryption key, webhook URL, timezone), HTTPS behind a reverse proxy, backups of both the database and the encryption key, updates, and when queue mode is worth it.
SBOMs and Signed Images: Software Supply Chain Security With Syft and Cosign
How to know what's in your container images and prove they came from your CI: generating SBOMs with Syft or BuildKit attestations, scanning them for vulnerabilities, signing images keylessly with Cosign and GitHub Actions OIDC, verifying by identity, adding SLSA provenance, and enforcing it at deploy time.