Safeguard
Security Guides•

What leaks into your container image without a .dockerignore file

A broad COPY sends your whole build context into the image, including env files, git history and keys. Here is what to exclude and how to check.

Safeguard Security Team
4 min read

Without a .dockerignore file, the build sends your entire project folder to the builder, and a line like COPY with a dot can put all of it into the image. That can include env files, private keys, git history, test data and local config. Exclude them by default and copy named paths.

How the leak happens

When you run a build, the directory you point at is the build context. Everything in it is available to COPY and ADD. A common line looks like this.

COPY . /app

That copies every file the builder can see, not only the code. Developers often have files in the project root that were never meant to ship: a local env file with a database URL, a cloud credentials file, a key used for a test, or an editor backup.

The Docker build guidance describes the ignore file as supporting exclusion patterns similar to gitignore, and says it keeps irrelevant files out of the build context without restructuring your repository.

What to exclude

Start with a deny-by-default idea and add exceptions, or at least cover these categories.

  • Secrets and local config. Env files, key and certificate files, credential folders, anything named like a token.
  • Version control data. The git directory holds full history, including commits that once contained a secret.
  • Dependencies you will reinstall. Local module folders and virtual environments, which can also differ from what the image should install.
  • Build output and caches. Old artifacts, coverage reports, logs.
  • Docs and tests that the runtime does not need.
  • The Dockerfile and the ignore file itself, which rarely need to be in the image.

A starting file might read:

.git
.env
.env.*
*.pem
*.key
node_modules
__pycache__
*.log
coverage
dist

Adjust it to your stack. If the app needs a built folder, copy it from a build stage instead.

Allowlist style

A safer pattern for sensitive projects is to ignore everything and then re-include what the build needs.

*
!src
!package.json
!package-lock.json

New files then stay out unless someone adds them on purpose. The tradeoff is that builds fail until you add a needed path, which is a feature rather than a bug.

Pair it with narrow COPY lines

The ignore file is a safety net. The better habit is to copy specific paths so the image holds what you chose. Combined with a multi-stage build, the final stage then receives a small set of files.

How to check what shipped

  1. Build the image.
  2. Start a container with a shell or export the filesystem.
  3. List the app directory and look for anything you did not expect.
  4. Search for files with key, env or pem in the name.

Also check old images. Tags built before you added the ignore file may still hold what you meant to exclude, and those layers remain in the registry until removed.

Safeguard's SBOM and dependency scanning, plus policies and gates, can add a check to your pipeline so a risky image fails before it is pushed. A free scan is the quickest way to try it on an existing image.

Quick check

Does the ignore file stop ADD from fetching a URL?

No. It filters files in the local build context. Remote downloads are a separate question, covered in the ADD versus COPY guide.

Is gitignore enough?

No. The builder reads the build context from the folder, not from git, so ignored-by-git files can still be copied unless the docker ignore file excludes them.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.