Dockleとは
DockleはセキュリティのためのDockerイメージのLinter。Dockerfileのベストプラクティス のチェック、Dockerイメージのセキュリティ診断を行なう。
Dockleの使い方
Dockleのインストール
Dockleのインストールは以下のコマンドで行なう。
Macの場合はHomebrewでインストールできる。
$ brew install goodwithtech/r/dockle
他のOSの場合はReleases · goodwithtech/dockle から対応する パッケージをダウンロードしてインストールする。
確認用のDockerイメージの作成
Dockleの実行を確認するために以下のDockerfileを作成する。
$ mkdir dockle-test
$ cd dockle-test
Dockerfileは以下のようにする。
FROM public.ecr.aws/amazonlinux/amazonlinux:2023.2.20231011.0
ADD docker-compose.yml /docker-compose.yml
docker-compose.ymlを以下のようにする。
version: "3"
services:
linux:
build: .
Dockerイメージをビルドする。
$ docker compose build
Dockleの実行
Dockerイメージのビルドが完了したらDockleを実行する。
まずイメージの名前を確認する。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dockle-test_linux latest 6a4a5cc5b2f7 10 days ago 179MB
名前はdockle-test_linux
でタグはlatest
となっている。
Dockleの実行はDockerイメージ名:タグ名
を指定して以下のように行なう。
$ dockle イメージ名:タグ名
今回の場合は以下のようになる。
$ dockle dockle-test_linux:latest
実行結果は以下のように標準出力に出力される。
FATAL - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
* Use COPY : ADD docker-compose.yml /docker-compose.yml # buildkit
WARN - CIS-DI-0001: Create a user for the container
* Last user should not be root
WARN - DKL-DI-0006: Avoid latest tag
* Avoid 'latest' tag
INFO - CIS-DI-0005: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
* not found HEALTHCHECK statement
INFO - DKL-LI-0003: Only put necessary files
* unnecessary file : docker-compose.yml
レベル
Dockleの実行結果には5段階のレベルが付いている。
- FATAL
- WARN
- INFO
- SKIP
- PASS
チームやプロジェクトでどの段階までを許容するかを決めておき、そのレベル以上の結果が出た場合はエラーとするなどの運用を行なう。
どのレベル以上をエラーとするかは--exit-level
オプション(-l
オプション)で指定する。(後述)
デフォルトではWARN
以上の結果が出た場合は--exit-code
で指定した終了ステータス(デフォルトは0
)となる。
検出対象からの除外
コマンドオプションで除外する
dockleコマンドに--ignore
オプション(-i
オプション)を付け、除外したいルールのIDを指定すると検出対象から除外できる。
$ dockle -i DKL-DI-0006 dockle-test_linux:latest
FATAL - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
* Use COPY : ADD docker-compose.yml /docker-compose.yml # buildkit
WARN - CIS-DI-0001: Create a user for the container
* Last user should not be root
INFO - CIS-DI-0005: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
* not found HEALTHCHECK statement
INFO - DKL-LI-0003: Only put necessary files
* unnecessary file : docker-compose.yml
検出結果からDKL-DI-0006
が除外されている。
複数のIDを指定する場合は--ignore
オプション(-i
オプション)を繰り返し指定する。
$ dockle -i DKL-DI-0006 -i CIS-DI-0001 dockle-test_linux:latest
FATAL - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
* Use COPY : ADD docker-compose.yml /docker-compose.yml # buildkit
INFO - CIS-DI-0005: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
* not found HEALTHCHECK statement
INFO - DKL-LI-0003: Only put necessary files
* unnecessary file : docker-compose.yml
DKL-DI-0006、CIS-DI-0001が除外できている。
環境変数で除外する
DOCKLE_IGNORES
環境変数に除外したいルールのIDをカンマ区切りで指定すると検出対象から除外できる。
$ export DOCKLE_IGNORES=DKL-DI-0006
$ dockle dockle-test_linux:latest
FATAL - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
* Use COPY : ADD docker-compose.yml /docker-compose.yml # buildkit
WARN - CIS-DI-0001: Create a user for the container
* Last user should not be root
INFO - CIS-DI-0005: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
* not found HEALTHCHECK statement
INFO - DKL-LI-0003: Only put necessary files
* unnecessary file : docker-compose.yml
複数のルールを除外する場合はカンマ区切りで指定する。
$ export DOCKLE_IGNORES=DKL-DI-0006,CIS-DI-0001
$ dockle dockle-test_linux:latest
FATAL - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
* Use COPY : ADD docker-compose.yml /docker-compose.yml # buildkit
INFO - CIS-DI-0005: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
* not found HEALTHCHECK statement
INFO - DKL-LI-0003: Only put necessary files
* unnecessary file : docker-compose.yml
.dockleignoreで除外する
.dockleignore
ファイルを作成し、除外したいルールのIDを記述すると検出対象から除外できる。
$ echo "DKL-DI-0006" > .dockleignore
$ echo "CIS-DI-0001" >> .dockleignore
$ cat .dockleignore
DKL-DI-0006
CIS-DI-0001
$ dockle dockle-test_linux:latest
FATAL - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
* Use COPY : ADD docker-compose.yml /docker-compose.yml # buildkit
INFO - CIS-DI-0005: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
* not found HEALTHCHECK statement
INFO - DKL-LI-0003: Only put necessary files
* unnecessary file : docker-compose.yml
チェック項目
Dockleでチェックする項目は以下の3カテゴリー。
- CIS's Docker Image Checkpoints : CIS Benchmarkに準拠したチェック項目(CIS-から始まる項目)
- Dockle Checkpoints for Docker : Dockerfileに関するベストプラクティスに準拠したチェック項目(DKL-DI-から始まる項目)
- Dockle Checkpoints for Linux : Linuxに関するベストプラクティスに準拠したチェック項目(DKL-LI-から始まる項目)
Overview of best practices for writing Dockerfiles | Docker Docs
GitHub Actionsでの実行
GitHub ActionsでDockleを実行するにはerzz/dockle-action を使用すると簡単に設定できる。
name: dockle
on:
pull_request:
push:
branches:
- master
jobs:
dockle-test:
runs-on: ubuntu-latest
steps:
# Gitリポジトリをチェックアウト
- name: Checkout code
uses: actions/checkout@v4
# Dockerイメージを作成
- name: Build image
run: |
cd dockle-test
docker build -t dockle-test:${{ github.sha }} .
# Dockleでチェック
- name: Run Dockle
uses: erzz/dockle-action@v1
with:
image: 'dockle-test:${{ github.sha }}'
failure-threshold: fatal
exit-code: 1
上記の例ではFATALレベルの結果が出た場合はエラー(終了ステータスコード1)となるように設定している。
求めるレベルに応じてfailure-threshold
とexit-code
を設定する。
AWS CodeBuildでの実行
AWS CodeBuildに組み込むにはbuildspec.yml
にて以下の手順で記述する。
pre_build
フェーズ: Dockleをインストールbuild
フェーズ: Dockerイメージをビルドpost_build
フェーズ: Dockleでチェック
以下はbuildspec.yml
の例。
version: 0.2
phases:
pre_build:
commands:
# ECRへログイン
- AWS_ACCOUNT_ID=$(echo ${CODEBUILD_BUILD_ARN} | cut -f 5 -d :)
- aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
# Dockleの最新RPMをGitHubからダウンロードしてインストール
- VERSION=$(curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/') && rpm -ivh https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.rpm
# Dockerイメージ名を変数IMAGEへ設定
- REPO=$(aws ecr describe-repositories --repository-names dockle-test --output text --query "repositories[0].repositoryUri")
- IMAGE=$REPO:latest
build:
commands:
# Dockerイメージをビルド
- docker image build -t $IMAGE ./dockle-test
post_build:
commands:
# Dockleでチェック
- dockle --exit-code 1 --exit-level FATAL $IMAGE
- exit `echo $?`
# チェック済みのイメージをECRへプッシュ
- docker image push $IMAGE
Tips
ANSI エスケープシーケンスを消す(–no-output)
Dockleの実行結果をpbcopy
など別のコマンドに渡すと色をつけるためのANSIエスケープシーケンスが含まれてしまう。
$ dockle dockle-test_linux:latest | pbcopy
コピーした結果は以下のようになる。
[31mFATAL[0m - [36mCIS-DI-0009[0m: Use COPY instead of ADD in Dockerfile
* Use COPY : ADD docker-compose.yml /docker-compose.yml # buildkit
[35mINFO[0m - [36mCIS-DI-0005[0m: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
[35mINFO[0m - [36mCIS-DI-0006[0m: Add HEALTHCHECK instruction to the container image
* not found HEALTHCHECK statement
[35mINFO[0m - [36mDKL-LI-0003[0m: Only put necessary files
* unnecessary file : docker-compose.yml
[31m
などのANSIエスケープシーケンスが含まれており、人が読む場合は読みづらく、別のコマンドに渡す場合は処理が必要となり不便である。
--no-output
オプションを付けるとANSIエスケープシーケンスを消してくれる。
$ dockle --no-color dockle-test_linux:latest | pbcopy
コピーした結果は以下のようになる。
FATAL - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
* Use COPY : ADD docker-compose.yml /docker-compose.yml # buildkit
INFO - CIS-DI-0005: Enable Content trust for Docker
* export DOCKER_CONTENT_TRUST=1 before docker pull/build
INFO - CIS-DI-0006: Add HEALTHCHECK instruction to the container image
* not found HEALTHCHECK statement
INFO - DKL-LI-0003: Only put necessary files
* unnecessary file : docker-compose.yml
ANSIエスケープシーケンスが含まれない。
指定したレベルで終了ステータスを1にする(–exit-code、–exit-level)
dockle
コマンドの終了ステータスコードのデフォルトは0
で、CIに組み込む場合は成功とみなされる。
問題を検出した場合にプログラムへ失敗と認識してほしい場合は終了ステータスコードを1
など、0
以外に設定する必要がある。
問題検出時の終了ステータスコードを指定にするには--exit-code
オプション(-e
オプション)を付ける。
$ dockle --exit-code 1 dockle-test_linux:latest
WARN - CIS-DI-0001: Create a user for the container
* Last user should not be root
WARN - DKL-DI-0006: Avoid latest tag
* Avoid 'latest' tag
$ echo $?
1
上記のとおり--exit-code
オプション(-c
オプション)を付けるとWARN
レベル以上の問題を検出した場合に終了ステータスコードが1
となる。
問題検出のしきい値を変更したい場合は--exit-level
オプション(-l
オプション)を付ける。
$ dockle --exit-code 1 --exit-level FATAL dockle-test_linux:latest
WARN - CIS-DI-0001: Create a user for the container
* Last user should not be root
WARN - DKL-DI-0006: Avoid latest tag
* Avoid 'latest' tag
$ echo $?
0
$ dockle --exit-code 1 --exit-level FATAL dockle-test_linux:latest
FATAL - CIS-DI-0009: Use COPY instead of ADD in Dockerfile
* Use COPY : ADD docker-compose.yml /docker-compose.yml # buildkit
WARN - CIS-DI-0001: Create a user for the container
* Last user should not be root
WARN - DKL-DI-0006: Avoid latest tag
* Avoid 'latest' tag
$ echo $?
1
上記では--exit-level
オプション(-l
オプション)にFATAL
を指定しているのでFATAL
レベルの問題を検出した場合にのみ終了ステータスコードが1
となっている。