Hadolint是一个用Haskell 编写的开源Dockerfiles语法检查、优化工具。





  • OSX brew

    brew install hadolint
  • Windows scoop

    scoop install hadolint
  • docker

    docker pull hadolint/hadolint:latest-debian
    docker pull hadolint/hadolint:latest-alpine



  • $PWD/.hadolint.yaml
  • $XDG_CONFIG_HOME/hadolint.yaml
  • ~/.config/hadolint.yaml


hadolint --config /path/to/config.yaml Dockerfile


echo "export XDG_CONFIG_HOME=~/.hadolint" >> /etc/profile && \
mkdir ~/.hadolint && \
source /etc/profile && \

创建并编辑配置vi ~/.hadolint/hadolint.yaml

  - DL3000
  - SC1010



hadolint [-v|--version] [-c|--config FILENAME] [-f|--format ARG] [DOCKERFILE...] 
         [--ignore RULECODE] [--trusted-registry REGISTRY (e.g.]

  -h,--help                Show this help text
  -v,--version             Show version
  -c,--config FILENAME     Path to the configuration file
  -f,--format ARG          The output format for the results [tty | json |
                           checkstyle | codeclimate | codacy] (default: tty)
  --ignore RULECODE        A rule to ignore. If present, the ignore list in the
                           config file is ignored
  --trusted-registry REGISTRY (e.g.
                           A docker registry to allow to appear in FROM instructions


hadolint Dockerfile 
hadolint --ignore DL3003 --ignore DL3006 Dockerfile
# 或者
docker run --rm -i hadolint/hadolint < Dockerfile


Dockerfile:2 DL3020 Use COPY instead of ADD for files and folders
Dockerfile:3 DL3025 Use arguments JSON notation for CMD and ENTRYPOINT arguments




  • VSCode
  • Sublime Text 3
  • Vim and NeoVim
  • Atom


1、Travis CI

# Use container-based infrastructure for quicker build start-up
sudo: false
# Use generic image to cut start-up time
language: generic
  # Path to 'hadolint' binary
  HADOLINT: "${HOME}/hadolint"
  # Download hadolint binary and set it as executable
  - curl -sL -o ${HADOLINT} "$(uname -s)-$(uname -m)"
    && chmod 700 ${HADOLINT}
  # List files which name starts with 'Dockerfile'
  # eg. Dockerfile,, etc.
  - git ls-files --exclude='Dockerfile*' --ignored | xargs --max-lines=1 ${HADOLINT}

2、GitHub Actions

name: Lint Dockerfile
on: push
    runs-on: ubuntu-latest
      - uses: actions/checkout@v2
      - name: Lint Dockerfile
        uses: brpaz/hadolint-action@master
          dockerfile: "Dockerfile"

3、Gitlab CI

  image: hadolint/hadolint:latest-debian
    - hadolint Dockerfile

4、Jenkins declarative pipeline

stage ("lint dockerfile") {
    agent {
        docker {
            image 'hadolint/hadolint:latest-debian'
    steps {
        sh 'hadolint dockerfiles/* | tee -a hadolint_lint.txt'
    post {
        always {
            archiveArtifacts 'hadolint_lint.txt'

5、Jenkins K8S plugin

声明hadolint pod

- name: hadolint
  image: hadolint/hadolint:latest-debian
  imagePullPolicy: Always
    - cat
  tty: true
stage('lint dockerfile') {
    steps {
        container('hadolint') {
            sh 'hadolint dockerfiles/* | tee -a hadolint_lint.txt'
    post {
        always {
            archiveArtifacts 'hadolint_lint.txt'

6、Bitbucket Pipelines

    - step:
        image: hadolint/hadolint:latest-debian
          - hadolint Dockerfile




Rule 描述
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 use apk add =.
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 use gem install :
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 ..orcmd 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 ... exitin casecd` fails.
Copyright Curiouser all right reserved,powered by Gitbook该文件最后修改时间: 2022-05-16 17:26:46

results matching ""

    No results matching ""