Dockerfile: Security Linting
A Practical Security Linting Example with Hadolint
Like any other piece of code, Dockerfiles can be linted. Linting is the process of analyzing code for potential flaws, poor practices, and other issues. In the case of security, linting can help highlight potential security issues, best practices, and common mistakes.
In summary, linting Dockerfiles can help improve the security posture of images and the containers built on top of them.
In the following section, we will explore Hadolint, a smart Dockerfile linter that helps you build best practice Docker images. The linter parses the Dockerfile into an AST and performs rules on top of the AST. It stands on the shoulders of ShellCheck to lint the Bash code inside RUN instructions.
To start, let's take a look at our three Dockerfiles, one for the menu service, one for the QR service, and one for the PostgreSQL database:
menu-service Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
qr-service Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "app.py"]
menu-postgresql Dockerfile
FROM bitnami/postgresql:17.4.0-debian-12-r1
Let's install Hadolint before starting:
# Install Hadolint
URL=https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64
curl -sL $URL -o /usr/local/bin/hadolint
chmod +x /usr/local/bin/hadolint
To lint a Dockerfile, you can run the following command:
# Lint the menu-service Dockerfile
hadolint $HOME/RestQR/menu/Dockerfile
# Lint the qr-service Dockerfile
hadolint $HOME/RestQR/qr/Dockerfile
# Lint the menu-postgresql Dockerfile
hadolint $HOME/RestQR/postgresql/Dockerfile
This is an example of the output you should expect:
Dockerfile:4 DL3042 warning: Avoid use of cache directory with pip. Use `pip install --no-cache-dir `
This warning is telling you that at line number 4 of the Dockerfile, you should avoid using the cache directory with pip. Instead, you should use pip install --no-cache-dir. This is a good practice since --no-cache-dir prevents leftover pip cache files from increasing image size.
At first glance, this warning might seem benign, but it can have a significant impact on the performance and security of your Docker images. From the performance side, using --no-cache-dir can speed up the build process by avoiding the download of cached files. On the security side, it can prevent the inclusion of outdated or vulnerable packages in your images. In practice, cached files persist in the image, even if they are no longer needed. This can lead to outdated or vulnerable packages being included in the image, which may increase the attack surface of the container.
To fix this issue, you can update your Dockerfiles manually or run the following command:
# Find and replace
find $HOME/RestQR -type f \
-name Dockerfile \
-exec sed \
-i 's/pip install -r requirements.txt/pip install --no-cache-dir -r requirements.txt/g' {} \;
However, if you want to ignore this warning (not recommended), you can add a .hadolint.yaml file to your project directory with the following content:
# $HOME/RestQR/.hadolint.yamlDevSecOps in Practice
A Hands-On Guide to Operationalizing DevSecOps at ScaleEnroll now to unlock current content and receive all future updates for free. Your purchase supports the author and fuels the creation of more exciting content. Act fast, as the price will rise as the course nears completion!
