dockerignore is a file filter library compatible with Docker and the node-ignore API
npm install @balena/dockerignoredockerignore is a file filter library fully compatible with Docker's .dockerignore
file, exposing the
same API as the popular ignore package for the.gitignore format.
dockerignore is also:
* Compatible with Linux, macOS and Windows.
* Compact with 0 external dependencies (production install).
* A pure Javascript port of Docker's Golang implementation of the .dockerignore format.
* Well tested with hundreds of test cases including comparison against the actual behavior
of docker build on Windows and Linux.
* Relied on in production environments by
balena-cli,
now-cli
and other prominent projects built around Docker.
The .dockerignore spec has several differences from .gitignore:
- * in .gitignore matches everything, whereas in .dockerignore it only matches files in the
current directory (like glob). This difference is important when whitelisting after a * rule.
- abc in .gitignore matches all abc files and directories, however deeply nested, whereas
in .dockerignore it matches only at ./abc and not in subdirectories like ./somedir/abc.
- With .gitignore, when a parent directory is ignored, subdirectories cannot be re-added (using
!) since git simply avoids walking through the subtree as an optimization. With
.dockerignore, a subdirectory can be re-added even if a parent directory has been ignored.
- For a complete list of differences, check out the .gitignore
spec and the .dockerignore
spec.
The entire API. dockerignore started as a fork of
node-ignore, and even reuses the same index.d.ts file
for TypeScript definitions. Under the hood, node-ignore's matching logic was rewritten to closely
match Docker's implementation (modeled mainly around
dockerignore.go
and fileutils.go).
dockerignore works with Node.js version 8 and above, on Linux, macOS and Windows.
The code is compiled with Babel.
``bash`
npm install --save @balena/dockerignore
`js`
const ignore = require('@balena/dockerignore')
const ig = ignore().add(['.abc/*', '!.abc/d/'])
Typescript type definitions are also included:
`typescript`
import ignore from '@balena/dockerignore'
const ig = ignore().add(['.abc/*', '!.abc/d/'])
`js
const paths = [
'.abc/a.js', // filtered out
'.abc/d/e.js' // included
]
ig.filter(paths) // ['.abc/d/e.js']
ig.ignores('.abc/a.js') // true
`
`js`
paths.filter(ig.createFilter()); // ['.abc/d/e.js']
`js`
ig.filter(['.abc\\a.js', '.abc\\d\\e.js'])
// if the code above runs on windows, the result will be
// ['.abc\\d\\e.js']
dockerignore behaves just like the Docker CLI ("docker build") in relation to the backslash (\)/
and forward slash () characters:
OS | Location | Slash (/) | Backslash (\).dockerignore
------------ | ----------------------- | ---------------| --------------------
Linux, macOS | | Path separator | Escape characterfilter()
Linux, macOS | , ignores() | Path separator | Part of file name.dockerignore
Windows | | Path separator | Path separatorfilter()
Windows | , ignores() | Path separator | Path separator
This means that forward slashes can be used in the .dockerignore file for cross-platform
compatibility. This is consistent with how Windows works generally: both forward slashes
and backslashes are accepted as path separators by the Command Prompt (cmd.exe) or
PowerShell, and by library functions like the Golang
filepath.Clean or the Node.js
path.normalize.
The use of the backslash as an escape character (Linux and macOS only) is not documented in the
.dockerignore specification. "Reasonable" uses are probably to escape the few characters that.dockerignore
have a special meaning in the file, namely "*#!\" (excluding the double quotes),'\\b'
as opposed to characters that have a special meaning in regular
expressions
generally. The "escaping" behavior for any other characters (e.g. ) is undefined and subject
to implementation-specific interpretation that may change at any time.
Leading and trailing slashes (or backslashes on Windows) are removed from .dockerignore patterns,'/a'
so , 'a/' and '/a/' are all equivalent to 'a' in a .dockerignore file, and they all'a'
anchor to the "leftmost" directory when matching against relative paths. For example, pattern 'x'
is compared with for a given path 'x/y/z'. This follows Docker's Golang implementation for
compatibility. Conversely, a given absolute path will not match a non-wildcard pattern. More
examples:
`js`
ignore().add('a').ignores('a') // true
ignore().add('/a').ignores('a') // true
ignore().add('/a/').ignores('a') // true
ignore().add('a').ignores('/a') // false
ignore().add('/a').ignores('/a') // false
ignore().add('/a/').ignores('/a') // false
Considering pattern slash removal, the cases above may be reduced to:
`js`
ignore().add('a').ignores('a') // true
ignore().add('a').ignores('/a') // false
The 'false' outcome for these examples may appear to mismatch the behavior of "docker build", when
the source argument for the Dockerfile ADD
or COPY instructions is an absolute path
(starting with a slash). The explanation is that docker converts absolute source paths to relative
paths (relative to the "build context") prior to pattern matching:
https://github.com/moby/moby/blob/v19.03.8/pkg/archive/archive.go#L806
https://github.com/moby/moby/blob/v19.03.8/pkg/archive/archive.go#L825
... while dockerignore mirrors the implementation of the pattern matcher itself. The advice is
for your application to do the same as the docker CLI: use relative paths for pattern matching.
This is also generally more portable across different environments: development machine, CI
pipelines, servers or end user devices.
A pattern starting with '#' (hash) is ignored as a comment. The hash can be prefixed with
a slash or backslash in order to match a file name that also starts with a hash:
`js`
ignore().add('#abc').ignores('#abc') // false
ignore().add('/#abc').ignores('#abc') // true
ignore().add('\\#abc').ignores('#abc') // true
This works because of the leading slash removal from patterns described in Absolute
Paths.
Patterns starting with '!' (exclamation mark) define matching exclusions (exceptions) as'/!'
documented in the .dockerignore
specification. For
compatibility with Docker's implementation, patterns starting with or '!/' (but not'/!/') will also be considered exclusion patterns, in addition to slash removal described in'\\!'
Absolute Paths. Backslash escaping as may be used in order to match a
file or directory name that starts with the exclamation mark, but this is only possible on Linux
and macOS, not on Windows. Again, it only behaves this way for compatibility with Docker's
implementation.
Matching is case-insensitive by default, following the ignore APIignorecase: false
(ignorecase).
Note however that Docker performs case-sensitive matching.
Use the option to align with Docker's behavior:
`js`
const ig = ignore({ ignorecase: false }) // for case-sensitive matching
- pattern String|Ignore An ignore pattern string, or the Ignore instanceArray.
- patterns Array of ignore patterns.
Adds a rule or several rules to the current manager.
Returns this
pattern could either be a line of ignore pattern or a string of multiple ignore patterns, which means we could just ignore().add() the content of a ignore file:
`js`
ignore()
.add(fs.readFileSync(filenameOfGitignore).toString())
.filter(filenames)
pattern could also be an ignore instance, so that we could easily inherit the rules of another Ignore instance.
Returns Boolean whether pathname should be ignored.
`js`
ig.ignores('.abc/a.js') // true
Filters the given array of pathnames, and returns the filtered array.
- paths Array. The array of pathnames to be filtered.
Creates a filter function which could filter an array of paths with Array.prototype.filter.
Returns function(path) the filter function.
Contributions are always welcome!
1. Fork this repository to your own GitHub account and then clone it to your local device.
2. Install the dependencies: npm installdocker build`)
3. Add a test case (if applicable) and ensure it currently fails
4. Add code to pass the test
5. Make a pull request (additional tests will run on CI to ensure that your test case agrees with an actual
The initial work on this project was done by Pranay Prakash
(@pranaygp) / ▲ZEIT, Kael Zhang
(@kaelzhang) and the node-ignore
contributors.
Paulo Castro (@pdcastro) / balena.io
forked the repository in year 2020 (encouraged by
Zeit) and put in a
substantial effort on Windows support, cross-platform compatibility and testing, leading to release
1.0.0.