Aller au contenu

Améliorer vos Dockerfile avec Hadolint

logo devops

Introduction

Comment vérifier que nos Dockerfile respecte l’ensemble des bonnes pratiques DevOps ?

Très peu connu, Hadolint est l’outil qui va vous aider à faire un Dockerfile aux petits oignons. En effet, écrire des Dockerfile correcte n’est pas aussi simple qu’on pourrait l’imaginer. C’est là qu’intervient Hadolint !

Fonctionnement d’Hadolint

Hadolint est une CLI qui vous aide à vérifier que vos Dockerfiles respectent les meilleures pratiques. Hadolint stocke votre Dockerfile dans un arbre de syntaxe abstraite (AST), après quoi il exécute un ensemble de règles prédéfinies à l’aide de ShellCheck pour vérifier la qualité du code.

Installation d’Hadolint

Hadolint peut être installé avec asdf, vous savez au combien j’apprécie cet outil :

Terminal window
asdf plugin add hadolint
asdf install hadolint latest
asdf global hadolint latest
hadolint -v
Haskell Dockerfile Linter 2.12.0

Vérifier vos Dockerfile

Je vais prendre un exemple trouver sur github.

FROM python:3.11.0-slim AS builder
WORKDIR /tmp
RUN pip install poetry
COPY pyproject.toml poetry.lock* ./
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
FROM python:3.11.0-slim
ENV PYTHONUNBUFFERED 1
RUN useradd -s /bin/bash -m me && \
groupadd app && \
usermod -aG app me
RUN apt update && \
apt upgrade -y && \
rm -rf /var/lib/apt/lists/*
WORKDIR /src
COPY --from=builder /tmp/requirements.txt ./
RUN pip install --no-cache-dir --upgrade -r requirements.txt
COPY ./app /src/app
EXPOSE 80
CMD uvicorn app.main:app --host 0.0.0.0 --port 80

Au premier abord ce Dockerfile semble pas mal du tout non ? Alors vérifions avec Hadolint.

Terminal window
hadolint Dockerfile
Dockerfile:5 DL3013 warning: Pin versions in pip. Instead of `pip install <package>` use `pip install <package>==<version>` or `pip install --requirement <requirements file>`
Dockerfile:5 DL3042 warning: Avoid use of cache directory with pip. Use `pip install --no-cache-dir <package>`
Dockerfile:33 DL3025 warning: Use arguments JSON notation for CMD and ENTRYPOINT arguments

On voit qu’Hadolint nous donne plusieurs conseils :

  1. A la ligne 5 il conseille de fixer une version de poetry. Et oui jamais latest.
  2. A la même ligne 5 il indique que pour optimiser la taille de l’image il est conseillé d’utiliser l’option --no-cache-dir de pip. Attention c’est inutile, car cette instruction se trouve dans la première étape de notre Dockerfile.
  3. A la ligne 33 il conseille d’utiliser plutôt le format JSON pour les instructions CMD

Apportons les corrections :

FROM python:3.11.0-slim AS builder
WORKDIR /tmp
RUN pip install --no-cache-dir poetry==1.4.1
COPY pyproject.toml poetry.lock* ./
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
FROM python:3.11.0-slim
ENV PYTHONUNBUFFERED 1
RUN useradd -s /bin/bash -m me && \
groupadd app && \
usermod -aG app me
RUN apt update && \
apt upgrade -y && \
rm -rf /var/lib/apt/lists/*
WORKDIR /src
COPY --from=builder /tmp/requirements.txt ./
RUN pip install --no-cache-dir --upgrade -r requirements.txt
COPY ./app /src/app
EXPOSE 80
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port 80"]

On relance Hadolint :

Terminal window
hadolint Dockerfile

L’outil Hadolint ne retourne plus de conseils.

Plus loin

Si vous débutez dans l’écriture des Dockerfile, je vous propose de lire cette documentation.

Vous savez que je conseille de créer vos propres images de containers pour plus de sécurité. Donc cela veut dire que vous devez les stocker dans votre serveur de gestionnaire de versions de code et lui ajouter un pipeline CI/CD. Hadolint devrait être intégré à votre pipeline dans la phase de test. Il y a quelque temps, je vous avais montré comment mettre à jour vos images de containers avec renovate. Dans ce billet, j’utilise hadolint, donc vous pouvez vous en inspirer.