kakakakakku blog

Weekly Tech Blog: Keep on Learning!

GitHub Actions と hadolint を組み合わせて Dockerfile の静的解析を自動化しよう!

GitHub Actionshadolint (Haskell Dockerfile Linter) を組み合わせて,今まで雑に実装してきた Dockerfile の静的解析を自動化する環境を作った.できる限り Dockerfile Best Practices を意識していることもあり,警告はあまり多く出なかったけど,やはり CI (Continuous Integration) で気付ける安心感はある!

www.docker.com

hadolint (Haskell Dockerfile Linter)

hadolint を使うと Dockerfile に警告を出してくれる.また DockerfileRUN は,シェルスクリプトの Linter として有名な ShellCheck を使って警告を出してくれる.例えば FROM centos:latest のように FROM:latest を使うと,バージョンを指定して!と警告が出る.意識していても漏れることもあり hadolint 便利!

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

github.com

なお,hadolint の Wiki に現時点でサポートされているルール一覧と詳細が載っている.

DL~hadolint のルールで,SC~ShellCheck のルールとなる.ShellCheck は他にもルールがある.

  • DL3000 : Use absolute WORKDIR.
  • DL3001 : Command does not make sense in a container.
  • DL3002 : Last user should not be root.
  • DL3003 : Use WORKDIR to switch to a directory.
  • DL3004 : Do not use sudo.
  • DL3005 : Do not use apt-get upgrade or dist-upgrade.
  • DL3006 : Always tag the version of an image explicitly.
  • DL3007 : Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag.
  • DL3008 : Pin versions in apt get install.
  • DL3009 : Delete the apt-get lists after installing something.
  • DL3010 : Use ADD for extracting archives into an image.
  • DL3011 : Valid UNIX ports range from 0 to 65535.
  • DL3012 : Provide an email adress or URL as maintainer. 🚫DEPRECATED
  • DL3013 : Pin versions in pip.
  • DL3014 : Use the -y switch.
  • DL3015 : Avoid additional packages by specifying --no-install-recommends.
  • DL3016 : Pin versions in npm.
  • DL3017 : Do not use apk upgrade
  • DL3018 : Pin versions in apk add
  • DL3019 : Use the --no-cache switch
  • DL3020 : Use COPY instead of ADD for files and folders
  • DL3021 : COPY with more than 2 arguments requires the last argument to end with /
  • DL3022 : COPY --from should reference a previously defined FROM alias
  • DL3023 : COPY --from cannot reference its own FROM alias
  • DL3024 : FROM aliases (stage names) must be unique
  • DL3025 : Use arguments JSON notation for CMD and ENTRYPOINT arguments
  • DL3026 : Use only an allowed registry in the FROM image
  • DL3027 : Do not use apt as it is meant to be an end-user tool, use apt-get or apt-cache instead.
  • DL3028 : Pin versions in gem install
  • DL3029 : Do not use --platform= with FROM.
  • DL4000 : MAINTAINER is deprecated
  • DL4001 : Either use Wget or Curl but not both.
  • DL4003 : Multiple CMD instructions found. If you list more than one CMD then only the last CMD will take effect.
  • DL4004 : Multiple ENTRYPOINT instructions found. If you list more than one ENTRYPOINT then only the last ENTRYPOINT will take effect.
  • DL4005 : Use SHELL to change the default shell
  • DL4006 : Set the SHELL option -o pipefail before RUN with a pipe in
  • SC2046 : Quote this to prevent word splitting
  • SC2086 : Double quote to prevent globbing and word splitting.

GitHub Actions + hadolint

GitHub Actionshadolint を組み合わせる場合,Docker Hub に公開された hadolint の Docker イメージを使うこともできるけど,今回は GitHub Actions ですぐに使える Hadolint Action を使うことにした.

github.com

さっそく .github/workflows/workflow.yml に以下を設定する.GitHub に push をしたら,Hadolint Action を使って Dockerfile に対して hadolint を実行する単純なワークフローにした.

name: Workflow
on: push
jobs:
  build:
    name: Hadolint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Hadolint
        uses: brpaz/hadolint-action@master

今回サンプルとして,以下のヒドイ Dockerfile を実装し,GitHub に push をする.

FROM centos:latest

RUN vim hello.txt

RUN sudo pwd

ADD README.md /app/

EXPOSE 80000

GitHub Actions で実行結果を確認すると,以下のように「計5種類」の警告が出た.

  • DL3007 : FROM:latest を使っている
  • DL3001 : vim コマンドを使っている
  • DL3004 : sudo コマンドを使っている
  • DL3020 : COPY ではなく ADD を使っている
  • DL3011 : 0 ~ 65535 以外のポートを使っている
Dockerfile:1 DL3007 Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag
Dockerfile:3 DL3001 For some bash commands it makes no sense running them in a Docker container like `ssh`, `vim`, `shutdown`, `service`, `ps`, `free`, `top`, `kill`, `mount`, `ifconfig`
Dockerfile:5 DL3004 Do not use sudo as it leads to unpredictable behavior. Use a tool like gosu to enforce root
Dockerfile:7 DL3020 Use COPY instead of ADD for files and folders
Dockerfile:9 DL3011 Valid UNIX ports range from 0 to 65535

f:id:kakku22:20200707112041p:plain

まとめ

最近 GitHub Actions を使う機会があり,使えば使うほど楽しくなって,今回は hadolint と組み合わせてみた.Dockerfile を GitHub に push すると,自動的に静的解析をしてくれるのは便利!オススメ!

関連記事

GitHub Actions に入門するなら「GitHub Learning Lab」を使うと便利!という記事を書いた.

kakakakakku.hatenablog.com

シェルスクリプトを実装するときは ShellCheck をよく使っている.2017年に CircleCI と組み合わせた記事を書いた.

kakakakakku.hatenablog.com