Docker .dockerignore Pattern Tester

Check which files a .dockerignore actually excludes. Put the patterns above a line of three dashes and the paths below it.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Test. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A star with no slash

Matches at the top level only, which is the opposite of .gitignore

node_modules
*.log
---
app.log
logs/app.log

Brace expansion

Matched literally, so the pattern excludes nothing at all

*.{log,tmp}
---
app.log
app.tmp

A re-inclusion under an excluded directory

Works here, unlike in .gitignore, because the last match wins

secrets/
!secrets/public.pem
---
secrets/private.key
secrets/public.pem

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Copying a .gitignore across unchanged

    A single star does not cross a slash in .dockerignore, so patterns that matched at any depth in git now match only at the top level, and files you expected to be excluded are uploaded.

    Instead:Prefix them with **/ where you meant any depth.

  2. Using brace expansion

    Docker matches the braces literally. The pattern excludes nothing and looks correct in every other context.

    Instead:Write one line per alternative.

  3. Putting a negation above the exclusion it undoes

    The last matching pattern wins, so a negation only does work when an exclusion above it matched the same path.

    Instead:Order it exclusion first, negation second.

This is Go's glob dialect, not your shell's

Docker matches with Go's filepath.Match plus ** and !. Two of its rules differ from what the same string means in a shell or in .gitignore, and both differences make a pattern match less than expected.

A single star never crosses a slash

So *.log matches app.log and not logs/app.log. In .gitignore the same pattern matches at any depth, which is why a file copied across from one to the other stops working. **/*.log is the form that matches everywhere.

Braces are not expanded

*.{log,tmp} is matched literally, so it excludes a file whose name genuinely contains braces, which is to say nothing at all. Your shell expands them and so do most JavaScript glob libraries, so the pattern looks correct everywhere except where it runs.

The last matching pattern decides

Docker evaluates every pattern against every path rather than skipping the contents of an excluded directory, which is what .gitignore does. So secrets/ followed by !secrets/public.pem does re-include the file, and the same two lines reversed do not.

A pattern is anchored at the context root

There is no leading-slash anchor because everything is already relative to the root, and a leading slash is stripped. A pattern with no slash in it matches only at the top level.

A directory pattern covers its contents

node_modules excludes node_modules and everything under it, without needing a trailing slash or a star. The trailing slash is stripped and changes nothing.

Where this can be wrong

It implements the same rules and is not the same code. Unusual character classes and escaping are where a difference would show. When an answer matters, build with --progress=plain and read what was actually transferred.

More docker tools

Docker Container Image Reference Parser Is that a registry or a Docker Hub user? Dockerfile Linter What this image will do to you later docker run to Kubernetes YAML And the flags that have no equivalent Docker Compose to Kubernetes And why depends_on has no equivalent Docker Logging Driver Generator json-file never rotates Dockerfile Non-Root USER Generator Numeric, or Kubernetes rejects it Docker OCI Image Labels Generator One of them actually does something Docker Hub Pull Rate Limit Calculator Counted per IP, not per person Docker Registry Storage Calculator Deleting a tag frees nothing Docker Build Context Analyzer All of it uploads before anything runs Docker Compose to docker run Converter Names stop resolving Docker Compose Version Migrator version: is obsolete now Docker Compose Network and Port Viewer Everything reaches everything Docker Command Explainer Which flags hand over the host Docker BuildKit Cache Mount Generator apt deletes the cache you just mounted Docker BuildKit Secret Mount Generator ARG is in docker history forever Docker Image Manifest Viewer unknown/unknown is not broken Docker Image Config Viewer Anyone who can pull can read your Env Docker Registry Token Decoder Check the scope before the credentials Docker HEALTHCHECK Generator Docker does nothing when it fails Docker Network Subnet Calculator 31 networks, then it stops Docker History Analyzer The rm did not save anything Docker Run to Compose Converter Some flags have no equivalent Docker CMD and ENTRYPOINT Tester Why docker stop takes ten seconds Docker Port Mapping Tester -p reaches past your firewall Docker -v to --mount Converter -v invents missing directories Docker Restart Policy Simulator The backoff resets after ten seconds Docker Exit Code Explainer 137 is two different problems Docker CPU Limit Converter --cpu-shares limits nothing Docker Memory Limit Calculator -m 512m allows a gigabyte Docker Compose Interpolation Tester An unset variable is an empty string Docker Environment Variable Precedence Tester Your shell does not reach the container Docker Compose Override Merge Previewer An override can add a port, never remove one Dockerfile Multi-Stage Build Analyzer Which stages reach the image Dockerignore Validator It is not .gitignore

Elsewhere on the site