Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
OrganizationEventAdvent CalendarQiitadon (β)
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Dockerfile 정적분석하기 (hadolint)



hadolint로 Dockerfile을 정적분석 할 수 있습니다.
사용법도 간단합니다.
현재 Github 스타는 3500개 입니다.

설치 및 사용법

Linux, Windows, Mac 모두에서 설치하여 사용할 수 있습니다. (현재 최신 버전 v1.17.5)
리눅스로 보겠습니다.
실행방법은 2가지 입니다.

$ curl -L -O https://github.com/hadolint/hadolint/releases/download/v1.17.5/hadolint-Linux-x86_64
$ mv hadolint-Linux-x86_64 hadolint
$ chmod +x hadolint
$ ./hadolint Dockerfile # 실행


$ docker run --rm -i hadolint/hadolint < Dockerfile # 실행

간단한 Nginx Dockerfile 을 예로 보겠습니다.

최초 Dockerfile 작성 후, hadolint 실행시 4개의 지적사항이 발생됩니다.

FROM ubuntu:latest
RUN apt-get update && apt-get install -y -q nginx
COPY index.html /usr/share/nginx/html/
CMD ["nginx", "-g", "daemon off;"]
# 아웃풋 의미
# Dockerfile:<라인> <체크항목> <간략설명>
$ ./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
Dockerfile:2 DL3008 Pin versions in apt get install. Instead of `apt-get install <package>` use `apt-get install <package>=<version>`
Dockerfile:2 DL3009 Delete the apt-get lists after installing something
Dockerfile:2 DL3015 Avoid additional packages by specifying `--no-install-recommends`

아래와 같이 Dockerfile을 수정 후, hadolint 재실행하면 지적사항이 사라짐을 확인할 수 있습니다.

FROM ubuntu:18.04
RUN apt-get update && apt-get install -y -q --no-install-recommends nginx=1.17.10 && rm -rf /var/lib/apt/lists/*
COPY index.html /usr/share/nginx/html/
CMD ["nginx", "-g", "daemon off;"]
$ ./hadolint Dockerfile

전체 체크항목 리스트는 아래와 같습니다.
Dockerfile 문법 35개, Shell 문법 33개의 Rule이 존재합니다.

Rule Description
DL3000 Use absolute WORKDIR.
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.
DL3002 Last user should not be root.
DL3003 Use WORKDIR to switch to a directory.
DL3004 Do not use sudo as it leads to unpredictable behavior. Use a tool like gosu to enforce root.
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 address or URL as maintainer.
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. Instead of apk add <package> use apk add <package>=<version>.
DL3019 Use the --no-cache switch to avoid the need to use --update and remove /var/cache/apk/* when done installing packages.
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 a end-user tool, use apt-get or apt-cache instead
DL3028 Pin versions in gem install. Instead of gem install <gem> use gem install <gem>:<version>
DL4000 MAINTAINER is deprecated.
DL4001 Either use Wget or Curl but not both.
DL4003 Multiple CMD instructions found.
DL4004 Multiple ENTRYPOINT instructions found.
DL4005 Use SHELL to change the default shell.
DL4006 Set the SHELL option -o pipefail before RUN with a pipe in it
SC1000 $ is not used specially and should therefore be escaped.
SC1001 This \c will be a regular 'c' in this context.
SC1007 Remove space after = if trying to assign a value (or for empty string, use var='' ...).
SC1010 Use semicolon or linefeed before done (or quote to make it literal).
SC1018 This is a unicode non-breaking space. Delete it and retype as space.
SC1035 You need a space here
SC1045 It's not foo &; bar, just foo & bar.
SC1065 Trying to declare parameters? Don't. Use () and refer to params as $1, $2 etc.
SC1066 Don't use $ on the left side of assignments.
SC1068 Don't put spaces around the = in assignments.
SC1077 For command expansion, the tick should slant left (` vs ´).
SC1078 Did you forget to close this double-quoted string?
SC1079 This is actually an end quote, but due to next char, it looks suspect.
SC1081 Scripts are case sensitive. Use if, not If.
SC1083 This {/} is literal. Check expression (missing ;/\n?) or quote it.
SC1086 Don't use $ on the iterator name in for loops.
SC1087 Braces are required when expanding arrays, as in ${array[idx]}.
SC1095 You need a space or linefeed between the function name and body.
SC1097 Unexpected ==. For assignment, use =. For comparison, use [ .. ] or [[ .. ]].
SC1098 Quote/escape special characters when using eval, e.g. eval "a=(b)".
SC1099 You need a space before the #.
SC2002 Useless cat. Consider cmd < file | .. or cmd file | .. instead.
SC2015 Note that A && B || C is not if-then-else. C may run when A is true.
SC2026 This word is outside of quotes. Did you intend to 'nest '"'single quotes'"' instead'?
SC2028 echo won't expand escape sequences. Consider printf.
SC2035 Use ./*glob* or -- *glob* so names with dashes won't become options.
SC2039 In POSIX sh, something is undefined.
SC2046 Quote this to prevent word splitting
SC2086 Double quote to prevent globbing and word splitting.
SC2140 Word is in the form "A"B"C" (B indicated). Did you mean "ABC" or "A\"B\"C"?
SC2154 var is referenced but not assigned.
SC2155 Declare and assign separately to avoid masking return values.
SC2164 Use cd ... || exit in case cd fails.


Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Help us understand the problem. What are the problem?