dockerfilelint
is an node module that analyzes a Dockerfile and looks for common traps, mistakes and helps enforce best practices.
Global installation with npm package manager.
npm install -g dockerfilelint
Start unit tests with npm test
, yarn run test
, or docker-compose -f docker-compose.test.yml up
./bin/dockerfilelint <path/to/Dockerfile>
Usage: dockerfilelint [files | content..] [options]
Options:
-o, --output Specify the format to use for output of linting results. Valid values
are `json` or `cli` (default). [string]
-j, --json Output linting results as JSON, equivalent to `-o json`. [boolean]
-v, --version Show version number [boolean]
-h, --help Show help [boolean]
Examples:
dockerfilelint Dockerfile Lint a Dockerfile in the current working
directory
dockerfilelint test/example/* -j Lint all files in the test/example directory and
output results in JSON
dockerfilelint 'FROM latest' Lint the contents given as a string on the
command line
dockerfilelint < Dockerfile Lint the contents of Dockerfile via stdin
You can configure the linter by creating a .dockerfilelintrc
with the following syntax:
rules:
uppercase_commands: off
The keys for the rules can be any file in the /lib/reference.js file. At this time, it's only possible to disable rules. They are all enabled by default.
The following rules are supported:
required_params
uppercase_commands
from_first
invalid_line
sudo_usage
apt-get_missing_param
apt-get_recommends
apt-get-upgrade
apt-get-dist-upgrade
apt-get-update_require_install
apkadd-missing_nocache_or_updaterm
apkadd-missing-virtual
invalid_port
invalid_command
expose_host_port
label_invalid
missing_tag
latest_tag
extra_args
missing_args
add_src_invalid
add_dest_invalid
invalid_workdir
invalid_format
apt-get_missing_rm
deprecated_in_1.13
You can add your own custom rulesets by supplying the -r option to dockerfilelint. Simply create a ruleset.js file first. It must export the "rules" variable with the proper keys. Here is an example of a simple two-rule ruleset file.
module.exports.rules = {
'add_prohibited': {
'title': 'ADD Command Prohibited',
'description': 'ADD command is not allowed! Use copy instead!',
'category': 'Optimization',
'function': ({ cmd, args, line, instruction }) => {
return cmd.toLowerCase() === 'add';
}
},
'avoid_curl_bashing': {
'title': 'Avoid Curl Bashing',
'description': 'Do not pipe bash or wget commands directly to shell. This is very insecure and can cause many issues with security. If you must, make sure to vet the script and verify its authenticity. E.G. "RUN wget http://my_website/script.sh | sh" is prohibited',
'category': 'Optimization',
'function': ({ cmd, line, args}) => {
// This function doesn't care about full instruction so it omits if from arguments
return cmd.toLowerCase() === 'run' && args.match(/(curl|wget)[^|^>]*[|>]/);
}
},
}
Notice, if a rule function returns true, it will be sent as a message to the reporter, otherwise it will be ignored for that line.
After you have your ruleset defined, simply call dockerfilelint with the -r command to pass the ruleset file in:
dockerfilelint -r path/to/ruleset.js path/to/Dockerfile
(Replace the pwd
/Dockerfile with the path to your local Dockerfile)
docker run -v `pwd`/Dockerfile:/Dockerfile replicated/dockerfilelint /Dockerfile
If you don't want to install this locally you can try it out on https://fromlatest.io.
- This should be the first command in the Dockerfile
- Base image should specify a tag
- Base image should not use latest tag
- Support
FROM scratch
without a tag - Support the
FROM <image>@<digest>
syntax - Allow config to specify "allowed" base layers
- Should be followed by exactly 1 parameter (@ sign)
- sudo is not included in the command
- apt-get [install | upgrade | remove] should include a -y flag
- apt-get install commands should include a
--no-install-recommends
flag - apt-get install commands should be paired with a
rm -rf /var/lib/apt/lists/*
in the same layer - Avoid running
apt-get upgrade
orapt-get dist-upgrade
- Never run
apt-get update
withoutapt-get install
on the same line - apk add commands should include a
--no-cache
flag or be paired with an--update
flag withrm -rf /var/cache/apk/*
in the same layer - apk add support for --virtual flag
- handle best practices for yum operations and cleanup
- Only a single
CMD
layer is allowed - Better handling of escaped quotes
- Detect exec format with expected variable substitution
- Format should be key=value
- Only the container port should be listed
- All ports should be exposed in a single cache layer (line)
- The same port number should not be exposed multiple times
- Exposed ports should be numeric and in the accepted range
- Format of
ENV
- Best practice of only using a single
ENV
line to reduce cache layer count
- Command should have at least 2 parameters
- Source command(s) cannot be absolute or relative paths that exist outside of the current build context
- Commands with wildcards or multiple sources require that destination is a directory, not a file
- If an
ADD
command could be aCOPY
, thenCOPY
is preferred - Using
ADD
to fetch remote files is discouraged because they cannot be removed from the layer
- Implement checking (similar to ADD)
- Do not
COPY
multiple files on a single command to best use cache
- Support
- Format
- Any build steps after VOLUME is declare should not change VOLUME contents
- If JSON format, double quotes are required
- Should be followed by exactly 1 parameter
- Validate that it has exactly 1 parameter
-
WORKDIR
can only expand variables previously set inENV
commands
- Support
- Prevent redefining the built in ARGs (proxy)
- Support
- Validate input
- Only present one time
- No additional parameters when only parameter is
NONE
- Options before
CMD
are valid - Options before
CMD
have additional arguments
- Only valid Dockerfile commands are present
- All commands should have at least 1 parameter
- Check that commands are written as upper case commands