プログラミング

hadolintを使ってDockerfileの健全性をチェックする

こんにちは、ましです

Docker/Kubernetes 実践コンテナ開発入門 という本を読んでいたらhadolintというものを知ったので使ってみようと思います。

hadolintとは

Haskellで書かれたDockerfileのlintツールです。DockerfileをASTに変換し、Dockerfileのベストプラクティスに従っているかどうか確認してくれるようです。どんなことが通知されるかは Rulesに記載れています。

使い方

Dockerfileの存在するディレクトリで以下のコマンドを実行するだけです。

docker run --rm -i hadolint/hadolint < Dockerfile

homebrewなどでもインストールできるようですがDocker環境あるならDockerでいい気がします。

実際に使ってみる

DockerでRailsの本番環境を作るで作成したDockerfileに対して実行してみた結果が以下になります。

/dev/stdin:5 DL3018 Pin versions in apk add. Instead of `apk add <package>` use `apk add <package>=<version>`
/dev/stdin:19 DL3020 Use COPY instead of ADD for files and folders
/dev/stdin:25 DL3020 Use COPY instead of ADD for files and folders
/dev/stdin:43 DL3018 Pin versions in apk add. Instead of `apk add <package>` use `apk add <package>=<version>`

2種類でたので一つずつ解決しようと思います。

DL3018 Pin versions in apk add. Instead of apk add <package> use apk add <package>=<version>

インストールする際にバージョンを固定しましょうってことですね。

RUN apk --update --no-cache add --virtual build-dependencies \
 shadow sudo busybox-suid mariadb-connector-c-dev tzdata alpine-sdk

しかしどのバージョンが適切なのかまではわからないので今インストールされているバージョンを確認することにした。

# apk -v info
...{Dockerfileに記載しないものの表示は省略}...
shadow-4.5-r0
sudo-1.8.23-r4
busybox-suid-1.28.4-r3
mariadb-connector-c-3.0.4-r1
mariadb-connector-c-dev-3.0.4-r1
tzdata-2020a-r0
execline=2.5.0.0-r0
libstdc++=6.4.0-r9

これらのバージョンを指定します。alpine-sdkは実際に使用するイメージに残らず、上記方法で取得できなかったのでパッケージのページを見て決めました。

#5行目のマルチステージビルドに使う前提用のインストール
RUN apk --update --no-cache add --virtual build-dependencies \
 shadow=4.5-r0 sudo=1.8.23-r4 busybox-suid=1.28.4-r3 mariadb-connector-c-dev=3.0.4-r1 tzdata=2020a-r0 alpine-sdk=1.0-r0
#43行目の実際に使用するイメージ用のインストール
RUN apk --update --no-cache -q add shadow=4.5-r0 sudo=1.8.23-r4 busybox-suid=1.28.4-r3 execline=2.5.0.0-r0 tzdata=2020a-r0 mariadb-connector-c-dev=3.0.4-r1 libstdc++=6.4.0-r9 && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

DL3020 Use COPY instead of ADD for files and folders

ADDの代わりにCOPYを使用しなさいってことですね。COPYは単にファイルをコピーするだけですが、ADDは圧縮の展開なども勝手に行ってくれるが故にセキュリティ的な問題があり得るので特に理由がなければCOPYの使用が推奨されているようです。

これは単にADDをCOPYに置き換えるだけですね

# 依存しているライブラリのインストール
COPY Gemfile Gemfile.lock ./
#yarn install
COPY package.json yarn.lock ./

終わりに

今回の変更点はこちらです

ベストプラクティスを全て理解して書くのは中々大変なのでこのように自動でチェックしてくれるのは嬉しいですね。ただ、Dockerfileはコードに比べると変更が少ないのでCIなどに組み込むべきかは微妙かな〜って気がします(CI回すのも無料じゃないので)