Suggest an editImprove this articleRefine the answer for “What is .dockerignore and why do you need it?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`.dockerignore`** is a gitignore-style file that tells Docker which files to exclude from the build context. Without it, every file in the build directory (including `node_modules`, `.git`, secrets) gets sent to the daemon and may end up in your image. ``` # .dockerignore — typical contents node_modules .git dist *.log .env* Dockerfile* README.md .vscode coverage ``` **Key:** smaller build context = faster builds, smaller images, fewer secrets leaked. The first file you should add to any project that has a Dockerfile.Shown above the full answer for quick recall.Answer (EN)Image**`.dockerignore`** is the simplest Docker file you will ever write. It is also one of the most impactful: it controls what gets sent to the daemon during `docker build` and prevents three classes of bugs (slow builds, bloated images, leaked secrets). ## Theory ### TL;DR - **Build context** = the directory you give to `docker build`. Everything in it gets uploaded to the daemon before the build starts. - Without `.dockerignore`, the WHOLE directory is sent — `node_modules`, `.git`, build outputs, IDE config, secrets, the lot. - `.dockerignore` syntax is gitignore-like with one exception: only one `**` glob pattern type, no negation in some Docker versions. - Should be at the **build context root** (next to `Dockerfile`). - **Three reasons it matters:** build speed, image size, security. ### Quick example ``` # .dockerignore node_modules .git dist build *.log *.tmp .env* .DS_Store Dockerfile* .dockerignore README.md .vscode .idea coverage tests *.test.js *.spec.ts ``` With this, `docker build .` only sends actual source files. Without it, a typical Node project sends 200+ MB of `node_modules` and a `.git` folder full of history that does not need to be in the image. ### Pattern syntax ``` # Comment *.log # any .log file at any depth logs/ # the logs directory and everything inside it !important.log # negation: include even if matched above **/temp # any 'temp' directory at any depth src/**/*.test.js # test files anywhere under src/ ``` **Important:** order matters. Later rules override earlier ones. Use `!` for exceptions. ### Why each entry matters #### `node_modules` (and equivalents) The single biggest contributor. Often hundreds of MBs. The Dockerfile reinstalls them via `npm ci` anyway. ``` node_modules vendor # PHP / Go / Ruby vendored deps .venv # Python virtualenv __pycache__ # Python bytecode cache *.pyc ``` #### `.git` The full git history. Often 50-500 MB on long-lived repos. Almost never needed in an image. Exception: if your build needs git info (commit SHA via `git rev-parse`), use `git rev-parse HEAD > VERSION` BEFORE build, then exclude `.git` and `COPY VERSION` only. #### Build outputs ``` dist build out target # Rust / Java ``` You rebuild these inside the image. No reason to ship the host's outputs in. #### Secrets and local config ``` .env* *.pem *.key secrets.yaml config.local.json ``` A `.env` accidentally COPYed into the image is a leaked production secret. #### IDE / editor / OS clutter ``` .vscode .idea .DS_Store # macOS Thumbs.db # Windows *.swp # vim ``` #### Tests and dev artifacts (sometimes) ``` coverage tests # if you do not run tests inside the image *.test.js ``` Depends on your build flow. If you `RUN npm test` inside the build (multi-stage), keep tests. Otherwise skip them. ### Common mistakes **No `.dockerignore` at all** ``` $ docker build -t myapp . [+] Building 0.0s => transferring context: 248.7MB ← too big ``` 248 MB upload to the daemon every build. Add `.dockerignore` and watch this drop to a few MB. **Forgetting that `COPY . .` copies whatever is in context** ```dockerfile COPY . . # copies everything — including .env if no .dockerignore ``` If `.env` exists in your build context AND it is not in `.dockerignore`, it lands in the image. Auditors love finding these. **Putting `.dockerignore` in a subdirectory** Docker only reads `.dockerignore` from the **build context root**. The build context is what you pass to `docker build` (typically `.` = current directory). A `.dockerignore` in `./api/.dockerignore` is ignored unless you build with `docker build ./api`. **Negating patterns and being surprised** ``` * !Dockerfile !src/** ``` This allow-listy pattern is fragile and order-dependent. Easier to use deny-list rules (`node_modules`, `.git`, `dist`). **Forgetting the file affects multi-stage builds too** The build context is determined once for `docker build`, regardless of how many stages your Dockerfile has. Every stage sees the same filtered context. ### Inspecting what is in the build context ```bash # See what would be uploaded docker build --no-cache --progress=plain -t test . 2>&1 | head -10 # Look for the "transferring context" line # Or do a dry run with a manual tar tar --exclude-from=.dockerignore -cf - . | wc -c ``` If you have ever wondered "why is my build context 1 GB?" — `du -sh */ .[^.]*/ 2>/dev/null | sort -h` from the build root tells you what is biggest. ### Real-world usage - **Every production project:** has a `.dockerignore`. The default starter for any new repo is to add it before the Dockerfile. - **Monorepos:** more important — `node_modules` directories per package can total gigabytes. - **CI builds:** large build context multiplied by every CI run = real disk and time costs. - **Cloud builds (Cloud Build, GitHub Actions):** they upload the context to a remote service. Smaller is faster (and cheaper). ### Follow-up questions **Q:** What happens if I `COPY` a file that is excluded by `.dockerignore`? **A:** Docker errors out with "file not found" — from Docker's perspective, the file is not in the context. **Q:** How is `.dockerignore` different from `.gitignore`? **A:** Same syntax (mostly). `.gitignore` controls what git tracks. `.dockerignore` controls what `docker build` sends to the daemon. Independent files, often overlapping but not identical (e.g., `.git` itself is not ignored by `.gitignore` but should be by `.dockerignore`). **Q:** Does `.dockerignore` affect `docker run -v` mounts? **A:** No. `.dockerignore` is build-time only. Bind mounts at run time mount whatever you point at, regardless of `.dockerignore`. **Q:** Can `.dockerignore` be in a different location? **A:** Yes, with BuildKit you can use `# syntax=docker/dockerfile:1.7` and a `<Dockerfile>.dockerignore` file. Useful when one repo has multiple Dockerfiles with different ignore needs. The default is still `.dockerignore` at the build context root. **Q:** (Senior) Why might a tightly-locked-down `.dockerignore` slow down dev workflow? **A:** If it excludes things that some Dockerfile expects to find (test fixtures, dev configs), `COPY` will fail or the image will misbehave. Common pitfall: excluding `.git` while a build step needs `git log` for a version. Solutions: pre-compute the value (`git rev-parse HEAD > VERSION` before build), pass via `--build-arg`, or use a per-Dockerfile `.dockerignore` variant for dev vs prod. ## Examples ### A typical Node project's `.dockerignore` ``` # Dependencies (rebuilt inside image) node_modules bower_components # Build outputs (rebuilt inside image) dist build out # Logs and temp *.log npm-debug.log* yarn-debug.log* yarn-error.log* # Environment / secrets .env .env.* !.env.example # keep example for documentation # Editors .vscode .idea *.swp .DS_Store # Tests / coverage coverage *.test.js *.spec.ts # Docker Dockerfile* .dockerignore compose*.yaml # VCS .git .gitignore .gitattributes ``` Result: a `docker build` context that contains exactly the source files needed. Build time drops dramatically; the image is smaller; no secrets leak. ### Before vs after measurement ```bash # Before .dockerignore $ time docker build -t myapp . [+] Building ... transferring context: 312.4MB real 1m45s # Add .dockerignore with node_modules and .git $ time docker build -t myapp . [+] Building ... transferring context: 4.2MB real 0m22s ``` Two lines in `.dockerignore`, 5x faster build. The numbers compound across CI runs. ### Multi-Dockerfile project (BuildKit) ``` repo/ ├── api/ │ ├── Dockerfile │ └── Dockerfile.dockerignore # specific to api ├── web/ │ ├── Dockerfile │ └── Dockerfile.dockerignore # specific to web └── .dockerignore # shared baseline ``` With `# syntax=docker/dockerfile:1.7`, BuildKit auto-loads `<Dockerfile>.dockerignore` if present, otherwise the root `.dockerignore`. Useful when api and web have different exclusion needs.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.