Hadolint: Comprehensive Guide to Lint Dockerfiles

Estimated reading time: 9 minutes

Last updated on October 25th, 2024 at 02:14 pm

Think of Dockerfiles as your building blueprint for creating Docker images. Adding linting to this process, you catch errors early and stick to best practices.

Why bother? Misconfigured Docker containers can be a headache – slow, heavy, and a pain for developers.

Hadolint is the best Dockerfile linter tool that can parse and analyze your Dockerfile and provide output that doesn’t match best practices per the Docker Guideline.

Dive into this comprehensive guide on linting Dockerfile.

DevOps Efficiency Hacks in Your Inbox! 📩

Stop wasting time searching. Get weekly tips & tutorials to streamline your DevOps workflow.

Subscribe Now!

What is Hadolint?

Hadolint, an open-source and smart Dockerfile linter created with Haskell to ensure your Dockerfiles follow the best practices. Following the best practices makes efficient Docker images meaning faster builds and smaller image sizes.

It parses your Dockerfile into an abstract syntax tree AST, it also uses ShellCheck – A shell script static analysis tool to lint bash/sh code in the Dockerfile.

How to build Docker Image 39x times faster?

Hadolint Dockerfile Linter

How to install Hadolint

Hadolint provides an easy-to-use CLI for all platforms. You can download the binaries for Linux, Mac, and Windows.

Install on Linux 🐧

You can install Hadolint in your Linux by following the below steps:

Download the latest binary from the Official GitHub Release

Bash
wget -O hadolint https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64

Once your downloading is finished, let’s move it to /usr/local/bin where we install third-party apps.

Bash
sudo mv hadolint /usr/local/bin/

Lastly, provide the execution permission

Bash
sudo chmod +x /usr/local/bin/hadolint

Install on Mac 🍎

You can install it on Mac using brew

Bash
brew install hadolint

Install on Windows 🪟

You can download the binary for Windows or use Scoop – a command-line installer for Windows.

Bash
scoop install hadolint

If you’re using Chocolatey – a package manager for Windows for installation, there’s a GitHub issue open for support.

Verify the installation

Let’s confirm the installation was successful

Bash
hadolint -v
Haskell Dockerfile Linter 2.12.0

How to Lint Dockerfile Using Hadolint

Using it is straightforward: once you install it on your system, run the command with your Dockerfile.

Let’s write a sample Dockerfile that isn’t optimized yet.

Bash
nano Dockerfile

Save the following content:

Dockerfile
FROM ubuntu:latest
MAINTAINER [email protected]
LABEL org.website="test.com"

COPY requirements.txt requirements.txt
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

COPY . code
WORKDIR /code

EXPOSE 8080

CMD python manage.py runserver 0.0.0.0:8080

Let’s run the linting with the above Dockerfile.

Bash
hadolint Dockerfile

Dockerfile:1 DL3007 warning: Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag
Dockerfile:2 DL4000 error: MAINTAINER is deprecated
Dockerfile:5 DL3003 warning: Use WORKDIR to switch to a directory
Dockerfile:5 SC2164 warning: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.
Dockerfile:7 DL3045 warning: `COPY` to a relative destination without `WORKDIR` set.
Dockerfile:9 DL3042 warning: Avoid use of cache directory with pip. Use `pip install --no-cache-dir <package>`
Dockerfile:9 DL3059 info: Multiple consecutive `RUN` instructions. Consider consolidation.
Dockerfile:12 DL3045 warning: `COPY` to a relative destination without `WORKDIR` set.
Dockerfile:17 DL3025 warning: Use arguments JSON notation for CMD and ENTRYPOINT arguments

That’s a lot of information in the output. Let’s break down what it means.

It parses your Dockerfile against a predefined set of rules line by line and for every violation provides the following structured output:

Bash
<LINE_NUMBER><RULE_CODE><SEVERITY_LEVEL>: <DESCRIPTION>

Let’s understand in detail.

Line Number

Provide the exact line number where the rule is violated. The below output shows that line number #1 has an issue:

Bash
Dockerfile:1 DL3007 warning: Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag

Rule Code

From the output, you can check it is prefixed with DL or SC

Bash
Dockerfile:5 DL3003 warning: Use WORKDIR to switch to a directory
Dockerfile:5 SC2164 warning: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.

Rule Code and Meaning

Rule CodePrefixDescription
DL3003DLThis means it comes from Linter.
SC2164SLThis means it comes from SpellCheck – A shell script static analysis tool,
Rule Code

You can find the detailed documentation for each of the rules including the information and how to fix it. For instance, warning DL303 you can find the documentation here.

Severity Level

Not all rules are treated equally, some rules are more important than others. The severity level shows how critical a rule violation is.

It categorizes severity levels into six levels: error, warning, info, style, ignore, and none.

Bash
Dockerfile:9 DL3059 info: Multiple consecutive `RUN` instructions. Consider consolidation.

For instance, Info is just informational, style suggests improvements.

You can also exclude severity levels that cause a failure by using the additional CLI option such as
--failure-threshold ( shortcut -t ). Remember that violated rules will still be reported but not cause failure.

Let’s modify the command to only fail on error violation not on info or warning:

Bash
hadolint --failure-threshold error Dockerfile

hadolint -t error Dockerfile

How to Ignore Rules in Hadolint

Following best practices is recommended, there might be cases where you want to ignore specific rules. It provides the flexibility to ignore one or more rules using the CLI option --ignore [RULECODE]

Let’s ignore the rule DL3059 by running the command:

Bash
hadolint --ignore DL3059 Dockerfile

You can ignore multiple rules by adding the same --ingore [RULECODE]

Bash
hadolint --ignore DL3059 --ignore DL3003 Dockerfile

Well, this approach is good for quick easy fixes but adding more rules makes it troublesome.

There’s a more easy and maintainable way to ignore such rules inline Dockerfile. You can exclude specific rules on a line-to-line basis by adding a comment:

Dockerfile
# hadolint ignore=DL3007
FROM ubuntu:latest

Level Up Your DevOps Skills! 📈

Get Weekly Tips, Tutorials & Master the Latest Trends – Subscribe Now!

Subscribe Now!

Customize Output Format for Hadolint

It supports various output format options (the default option is tty), this is very helpful especially when you want to integrate with other tools such as API and CI/CD pipeline.

You can customize the output format with the CLI option --format:

Bash
hadolint --format json Dockerfile

Below is the list of supported output formats:

  1. json – Provide the output in JSON structure format which can be used with API or scripts.
  2. checkstyle – Generate Checkstyle supported report.
  3. codeclimate – Generate Code Climate supported the report.
  4. gitlab_codeclimate – Works with the GitLab Code Quality feature. You can integrate with Gitlab CI for linting Pull Request.
  5. codacy – Generate Codacy-supported report.

Use this output format with your CI/CD pipeline.

Configuration file with Hadolint

Manually providing all the options every time you run the linting can be troublesome. You can simplify this process by adding all the options in a single configuration file named hadolint.yml

Configuration files can be used globally or project-specific. It will check the configuration file for the below folders:

$PWD/.hadolint.yaml
$XDG_CONFIG_HOME/hadolint.yaml
$HOME/.config/hadolint.yaml
$HOME/.hadolint/hadolint.yaml or $HOME/hadolint/config.yaml
$HOME/.hadolint.yaml

You can create a single configuration file and put it in the root of your repository, this way you can have consistency in writing the Dockerfile across the teams. By using this approach you can create a standardized practice that can be shared with developers and DevOps engineers.

You can check the Configuration Documentation for all the available configuration options.

Let’s create a hadolint.yml file with sample configuration:

YAML
failure-threshold: error
format: json
ignored:
- DL3059
- DL3003
strict-labels: false

In addition to the config file, you can also environment variables to configure it:

Let’s use the hadolint.yml config file:

Bash
hadolint --config hadolint.yml Dockerfile

Hadolint Integration with CICD Pipeline

Integrating within the CI/CD pipeline ensures the code quality from the start. By catching errors early in the pipeline you can streamline the process and follow the best practices.

Your CI/CD flow will look like the below:

  1. Docker Build CI Pipeline:
    • Include Hadolint in your Docker Build Pipeline.
    • Whenever a new Pull Request is raised, the pipeline will automatically check for the lining issues
  2. Prompt Feedback for Developer:
    • If the Dockerfile doesn’t match the defined standards, the build fails.
    • The developer can check the raised issues from the linting and fix them.
  3. Customize Configuration:
    • Define the custom hadolint.yml configuration that follows the organization’s standards.

It provides the out-of-the-box integration for the various tools:

Check out all the supported integrations.

Lint Dockerfile with Online Hadolint

You can try out the online version without installing anything in your system. This can be helpful for quickly testing your Dockerfile to prevent CI/CD failure.

Quickly try out the Online Hadolint from here.

hadolint online

Run Hadolint as a Docker Container

If you don’t want to install anything on your machine, another way to lint your Dockerfile is to run it as a container version. The prerequisite is you should have Docker installed ( I believe you do ).

You can run the below command to start the disposable Hadolint container:

Bash
docker run --rm -i ghcr.io/hadolint/hadolint < Dockerfile

This will work the same way and provide the output, once finished it’ll destroy the container.

Fast-Track Your DevOps Career 🚀

Stay ahead of the curve with the latest industry insights. Get weekly tips & propel your skills to the next level.

Subscribe Now!

Conclusion 

Hadolint is a great tool for making sure you’re lining your Docker image anywhere, every time.

Incorporating a linter into the workflow ensures our Dockerfiles are always readable, understandable, and maintainable whether in the cloud or on your local machine.

Key takeaway:

  • Easy to manage workflow by adding Linting into day-to-day development.
  • Build a small, fast, and secure Docker image.
  • Linting everywhere – Wherever you build your Dockerfile—on your laptop, in the cloud, or in CI pipelines—linting happens consistently.

This blog gives you a comprehensive guide using the Hadolint for lining Dockerfile. If you want to learn more about how to build your Dockerfile 39x faster, check our recent post on Docker Build 39x Times Faster: Docker Build Cloud.

If you’re looking for how to make your Docker container secure check out the Docker Container Security Cheatsheet and don’t get hacked🔐

Kashyap Merai
Kashyap Merai

Kashyap Merai, a Certified Solution Architect and Public Cloud Specialist with over 7 years in IT. He helped startups in Real Estate, Media Streaming, and On-Demand industries launch successful public cloud projects.

Passionate about Space, Science, and Computers, He also mentors aspiring cloud engineers, shaping the industry's future.

Connect with him on LinkedIn to stay updated on cloud innovations.