Docker Tip #89: Lint your Dockerfile with Hadolint
This can help you build images that stick to best practices and save time by detecting errors before you build your images.
If you prefer video, I recorded a demo video going over what’s written below.
Hadolint detects around 100 issues. These range from style choices to errors.
I recently added it to all of my Docker Compose example web app repos and it found a few things like forgetting to use the CMD array syntax in 1 spot, using
_ in a label key instead of
- (underscores are illegal characters as label keys) and forgetting to
set -o pipefail in a
RUN instruction when using Unix pipes.
What’s neat is it’s packaged into a Docker image so you don’t need to install anything locally to run it, although you can
brew install it as well as find it in other package managers.
Here’s how I’ve been running it as a Docker container:
docker container run --rm -i hadolint/hadolint hadolint --ignore DL3008 - < Dockerfile
In this case it’ll lint a
Dockerfile in the directory where you run the command.
DL3008 is related to version pinning all of your apt package versions in your Dockerfile. Personally I don’t think that’s worth it since your distro will lock those versions and ideally you would want security patches to be updated as you re-build your images periodically. A full list of rules can be found in hadolint’s documentation.
If you’re curious, it uses ShellCheck to lint your
RUN instructions which is fantastic.
If you find yourself wanting to customize hadolint a bit it does support the idea of a config file which you can volume mount into hadolint’s container when you run it. I haven’t used this since the default settings are solid minus that one rule I ignored.
I have hadolint running in CI to help detect issues automatically. This is one case where I like avoiding a specific image version and use
latest because as hadolint gets updated, it may add new rules. I like this because I re-build my images on a schedule and I want CI to break if my images aren’t sticking to current best practices.
If you want CI to stick to using the same Dockerized version of hadolint you can always use a specific version. A list of tags are available on the Docker Hub.