Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Dockerfile linter, validate inline bash, written in Haskell

License

NotificationsYou must be signed in to change notification settings

hadolint/hadolint

Repository files navigation

Build StatusGPL-3 licensedGitHub releaseGitHub downloadspipecat

A smarter Dockerfile linter that helps you buildbest practice Dockerimages. The linter parses the Dockerfile into an AST and performs rules ontop of the AST. It stands on the shoulders ofShellCheck to lintthe Bash code insideRUN instructions.

🌐Check the online version onhadolint.github.io/hadolintScreenshot

Table of Contents

How to use

You can runhadolint locally to lint your Dockerfile.

hadolint<Dockerfile>hadolint --ignore DL3003 --ignore DL3006<Dockerfile># exclude specific ruleshadolint --trusted-registry my-company.com:500<Dockerfile># Warn when using untrusted FROM images

Docker comes to the rescue, providing an easy way how to runhadolint on mostplatforms.Just pipe yourDockerfile todocker run:

docker run --rm -i hadolint/hadolint< Dockerfile# ORdocker run --rm -i ghcr.io/hadolint/hadolint< Dockerfile

or usingPodman:

podman run --rm -i docker.io/hadolint/hadolint< Dockerfile# ORpodman run --rm -i ghcr.io/hadolint/hadolint< Dockerfile

or using Windows PowerShell:

cat .\Dockerfile| docker run--rm-i hadolint/hadolint

Install

You can download prebuilt binaries for OSX, Windows and Linux from the latestrelease page. However, if this does not work for you, please fall back tocontainer (Docker),brew or source installation.

On OSX, you can usebrew to installhadolint.

brew install hadolint

On Windows, you can usescoop toinstallhadolint.

scoop install hadolint

On distributions that havenix installed, you can use thehadolintpackage to run ad-hoc shells or permanently installhadolint intoyour environment.

As mentioned earlier,hadolint is available as a container image:

docker pull hadolint/hadolint# ORdocker pull ghcr.io/hadolint/hadolint

If you need a container with shell access, use the Debian or Alpinevariants:

docker pull hadolint/hadolint:latest-debian# ORdocker pull hadolint/hadolint:latest-alpine# ORdocker pull ghcr.io/hadolint/hadolint:latest-debian# ORdocker pull ghcr.io/hadolint/hadolint:latest-alpine

You can also buildhadolint locally. You needHaskell and thecabalbuild tool to build the binary.

git clone https://github.com/hadolint/hadolint \&&cd hadolint \&& cabal configure \&& cabal build \&& cabal install

If you want theVS Code Hadolintextension to use Hadolint in a container, you can use the followingwrapper script:

#!/bin/bashdockerfile="$1"shiftdocker run --rm -i hadolint/hadolint hadolint"$@" -<"$dockerfile"

CLI

hadolint --help
hadolint - Dockerfile Linter written in HaskellUsage: hadolint [-v|--version] [-c|--config FILENAME] [DOCKERFILE...]                [--file-path-in-report FILEPATHINREPORT] [--no-fail]                [--no-color] [-V|--verbose] [-f|--format ARG] [--error RULECODE]                [--warning RULECODE] [--info RULECODE] [--style RULECODE]                [--ignore RULECODE]                [--trusted-registry REGISTRY (e.g. docker.io)]                [--require-label LABELSCHEMA (e.g. maintainer:text)]                [--strict-labels] [--disable-ignore-pragma]                [-t|--failure-threshold THRESHOLD]  Lint Dockerfile for errors and best practicesAvailable options:  -h,--help                Show this help text  -v,--version             Show version  -c,--config FILENAME     Path to the configuration file  --file-path-in-report FILEPATHINREPORT                           The file path referenced in the generated report.                           This only applies for the 'checkstyle' format and is                           useful when running Hadolint with Docker to set the                           correct file path.  --no-fail                Don't exit with a failure status code when any rule                           is violated  --no-color               Don't colorize output  -V,--verbose             Enables verbose logging of hadolint's output to                           stderr  -f,--format ARG          The output format for the results [tty | json |                           checkstyle | codeclimate | gitlab_codeclimate | gnu |                           codacy | sonarqube | sarif] (default: tty)  --error RULECODE         Make the rule `RULECODE` have the level `error`  --warning RULECODE       Make the rule `RULECODE` have the level `warning`  --info RULECODE          Make the rule `RULECODE` have the level `info`  --style RULECODE         Make the rule `RULECODE` have the level `style`  --ignore RULECODE        A rule to ignore. If present, the ignore list in the                           config file is ignored  --trusted-registry REGISTRY (e.g. docker.io)                           A docker registry to allow to appear in FROM                           instructions  --require-label LABELSCHEMA (e.g. maintainer:text)                           The option --require-label=label:format makes                           Hadolint check that the label `label` conforms to                           format requirement `format`  --strict-labels          Do not permit labels other than specified in                           `label-schema`  --disable-ignore-pragma  Disable inline ignore pragmas `# hadolint                           ignore=DLxxxx`  -t,--failure-threshold THRESHOLD                           Exit with failure code only when rules with a                           severity equal to or above THRESHOLD are violated.                           Accepted values: [error | warning | info | style |                           ignore | none] (default: info)

Configure

Configuration files can be used globally or per project.Hadolint looks for configuration files in the following locations or theirplatform specific equivalents in this order and uses the first one exclusively:

  • $PWD/.hadolint.yaml
  • $XDG_CONFIG_HOME/hadolint.yaml
  • $HOME/.config/hadolint.yaml
  • $HOME/.hadolint/hadolint.yaml or $HOME/hadolint/config.yaml
  • $HOME/.hadolint.yaml

In windows, the%LOCALAPPDATA% environment variable is used instead ofXDG_CONFIG_HOME. Config files can have eitheryaml oryml extensions.

hadolint fullyaml config file schema

failure-threshold:string# name of threshold level (error | warning | info | style | ignore | none)format:string# Output format (tty | json | checkstyle | codeclimate | gitlab_codeclimate | gnu | codacy)ignored:[string]# list of ruleslabel-schema:# See Linting Labels below for specific label-schema detailsauthor:string# Your namecontact:string# email addresscreated:timestamp# rfc3339 datetimeversion:string# semverdocumentation:string# urlgit-revision:string# hashlicense:string# spdxno-color:boolean# true | falseno-fail:boolean# true | falseoverride:error:[string]# list of ruleswarning:[string]# list of rulesinfo:[string]# list of rulesstyle:[string]# list of rulesstrict-labels:boolean# true | falsedisable-ignore-pragma:boolean# true | falsetrustedRegistries:string | [string]# registry or list of registries

hadolint supports specifying the ignored rules using a configurationfile. The configuration file should be inyaml format. This is onevalid configuration file as an example:

ignored:  -DL3000  -SC1010

Additionally,hadolint can warn you when images from untrustedrepositories are being used in Dockerfiles, you can append thetrustedRegistries keys to the configuration file, as shown below:

ignored:  -DL3000  -SC1010trustedRegistries:  -docker.io  -my-company.com:5000  -"*.gcr.io"

If you want to override the severity of specific rules, you can do that too:

override:error:    -DL3001    -DL3002warning:    -DL3042    -DL3033info:    -DL3032style:    -DL3015

failure-threshold Exit with failure code only when rules with aseverity above THRESHOLD are violated (Available in v2.6.0+)

failure-threshold:infooverride:warning:    -DL3042    -DL3033info:    -DL3032

Additionally, you can pass a custom configuration file in the command line withthe--config option

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

To pass a custom configuration file (using relative or absolute path) toa container, use the following command:

docker run --rm -i -v /your/path/to/hadolint.yaml:/.config/hadolint.yaml hadolint/hadolint< Dockerfile# ORdocker run --rm -i -v /your/path/to/hadolint.yaml:/.config/hadolint.yaml ghcr.io/hadolint/hadolint< Dockerfile

In addition to config files, Hadolint can be configured with environmentvariables.

NO_COLOR=1# Set or unset. See https://no-color.orgHADOLINT_NOFAIL=1# Truthy value e.g. 1, true or yesHADOLINT_VERBOSE=1# Truthy value e.g. 1, true or yesHADOLINT_FORMAT=json# Output format (tty | json | checkstyle | codeclimate | gitlab_codeclimate | gnu | codacy | sarif )HADOLINT_FAILURE_THRESHOLD=info# threshold level (error | warning | info | style | ignore | none)HADOLINT_OVERRIDE_ERROR=DL3010,DL3020# comma separated list of rule codesHADOLINT_OVERRIDE_WARNING=DL3010,DL3020# comma separated list of rule codesHADOLINT_OVERRIDE_INFO=DL3010,DL3020# comma separated list of rule codesHADOLINT_OVERRIDE_STYLE=DL3010,DL3020# comma separated list of rule codesHADOLINT_IGNORE=DL3010,DL3020# comma separated list of rule codesHADOLINT_STRICT_LABELS=1# Truthy value e.g. 1, true or yesHADOLINT_DISABLE_IGNORE_PRAGMA=1# Truthy value e.g. 1, true or yesHADOLINT_TRUSTED_REGISTRIES=docker.io# comma separated list of registry urlsHADOLINT_REQUIRE_LABELS=maintainer:text# comma separated list of label schema items

Non-Posix Shells

When using base images with non-posix shells as default (e.g. Windows basedimages) a special pragmahadolint shell can specify which shell the base imageuses, so that Hadolint can automatically ignore all shell-specific rules.

FROM mcr.microsoft.com/windows/servercore:ltsc2022# hadolint shell=powershellRUN Get-Process notepad | Stop-Process

Ignoring Rules

Inline ignores

It is also possible to ignore rules by adding a special comment directlyabove the Dockerfile statement for which you want to make an exception for.Such comments look like# hadolint ignore=DL3001,SC1081. For example:

# hadolint ignore=DL3006FROM ubuntu# hadolint ignore=DL3003,SC1035RUN cd /tmp && echo"hello!"

The comment "inline ignores" applies only to the statement following it.

Global ignores

Rules can also be ignored on a per-file basis using the global ignore pragma.It works just like inline ignores, except that it applies to the whole fileinstead of just the next line.

# hadolint global ignore=DL3003,DL3006,SC1035FROM ubuntuRUN cd /tmp && echo"foo"

Linting Labels

Hadolint is able to check if specific labels are present and conformto a predefined label schema.First, a label schema must be defined either via the command line:

hadolint --require-label author:text --require-label version:semver Dockerfile

or via the config file:

label-schema:author:textcontact:emailcreated:rfc3339version:semverdocumentation:urlgit-revision:hashlicense:spdx

The value of a label can be either oftext,url,semver,hash orrfc3339:

SchemaDescription
textAnything
rfc3339A time, formatted according toRFC 3339
semverAsemantic version
urlA URI as described inRFC 3986
hashEither a short or a longGit hash
spdxAnSPDX license identifier
emailAn email address conforming toRFC 5322

By default, Hadolint ignores any label that is not specified in the label schema. Towarn against such additional labels, turn on strict labels, using the command line:

hadolint --strict-labels --require-label version:semver Dockerfile

or the config file:

strict-labels:true

When strict labels is enabled, but no label schema is specified,hadolintwill warn if any label is present.

Note on dealing with variables in labels

It is a common pattern to fill the value of a label not statically, but ratherdynamically at build time by using a variable:

FROM debian:busterARG VERSION="du-jour"LABEL version="${VERSION}"

To allow this, the label schema must specifytext as value for that label:

label-schema:version:text

Integrations

To get most ofhadolint, it is useful to integrate it as a check in your CIor into your editor, or as a pre-commit hook, to lint yourDockerfile as youwrite it. See ourIntegration docs.

Rules

An incomplete list of implemented rules. Click on the error code to get moredetailed information.

  • Rules with the prefixDL are fromhadolint. Have a look atRules.hs to find the implementation of the rules.

  • Rules with theSC prefix are fromShellCheck (only the mostcommon rules are listed, there are dozens more).

Pleasecreate an issue if you have an idea for a good rule.

RuleDefault SeverityDescription
DL1001IgnorePlease refrain from using inline ignore pragmas# hadolint ignore=DLxxxx.
DL3000ErrorUse absolute WORKDIR.
DL3001InfoFor some bash commands it makes no sense running them in a Docker container like ssh, vim, shutdown, service, ps, free, top, kill, mount, ifconfig.
DL3002WarningLast user should not be root.
DL3003WarningUse WORKDIR to switch to a directory.
DL3004ErrorDo not use sudo as it leads to unpredictable behavior. Use a tool like gosu to enforce root.
DL3006WarningAlways tag the version of an image explicitly.
DL3007WarningUsing latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag.
DL3008WarningPin versions inapt-get install.
DL3009InfoDelete the apt-get lists after installing something.
DL3010InfoUse ADD for extracting archives into an image.
DL3011ErrorValid UNIX ports range from 0 to 65535.
DL3012ErrorMultipleHEALTHCHECK instructions.
DL3013WarningPin versions in pip.
DL3014WarningUse the-y switch.
DL3015InfoAvoid additional packages by specifying--no-install-recommends.
DL3016WarningPin versions innpm.
DL3018WarningPin versions inapk add. Instead ofapk add <package> useapk add <package>=<version>.
DL3019InfoUse the--no-cache switch to avoid the need to use--update and remove/var/cache/apk/* when done installing packages.
DL3020ErrorUseCOPY instead ofADD for files and folders.
DL3021ErrorCOPY with more than 2 arguments requires the last argument to end with/
DL3022WarningCOPY --from should reference a previously definedFROM alias
DL3023ErrorCOPY --from cannot reference its ownFROM alias
DL3024ErrorFROM aliases (stage names) must be unique
DL3025WarningUse arguments JSON notation for CMD and ENTRYPOINT arguments
DL3026ErrorUse only an allowed registry in theFROM image
DL3027WarningDo not useapt as it is meant to be an end-user tool, useapt-get orapt-cache instead
DL3028WarningPin versions in gem install. Instead ofgem install <gem> usegem install <gem>:<version>
DL3029WarningDo not use --platform flag with FROM.
DL3030WarningUse the-y switch to avoid manual inputyum install -y <package>
DL3032Warningyum clean all missing after yum command.
DL3033WarningSpecify version withyum install -y <package>-<version>
DL3034WarningNon-interactive switch missing fromzypper command:zypper install -y
DL3035WarningDo not usezypper dist-upgrade.
DL3036Warningzypper clean missing after zypper use.
DL3037WarningSpecify version withzypper install -y <package>[=]<version>.
DL3038WarningUse the-y switch to avoid manual inputdnf install -y <package>
DL3040Warningdnf clean all missing after dnf command.
DL3041WarningSpecify version withdnf install -y <package>-<version>
DL3042WarningAvoid cache directory withpip install --no-cache-dir <package>.
DL3043ErrorONBUILD,FROM orMAINTAINER triggered from withinONBUILD instruction.
DL3044ErrorDo not refer to an environment variable within the sameENV statement where it is defined.
DL3045WarningCOPY to a relative destination withoutWORKDIR set.
DL3046Warninguseradd without flag-l and high UID will result in excessively large Image.
DL3047Infowget without flag--progress will result in excessively bloated build logs when downloading larger files.
DL3048StyleInvalid Label Key
DL3049InfoLabel<label> is missing.
DL3050InfoSuperfluous label(s) present.
DL3051WarningLabel<label> is empty.
DL3052WarningLabel<label> is not a valid URL.
DL3053WarningLabel<label> is not a valid time format - must conform to RFC3339.
DL3054WarningLabel<label> is not a valid SPDX license identifier.
DL3055WarningLabel<label> is not a valid git hash.
DL3056WarningLabel<label> does not conform to semantic versioning.
DL3057IgnoreHEALTHCHECK instruction missing.
DL3058WarningLabel<label> is not a valid email format - must conform to RFC5322.
DL3059InfoMultiple consecutiveRUN instructions. Consider consolidation.
DL3060Infoyarn cache clean missing afteryarn install was run.
DL3061ErrorInvalid instruction order. Dockerfile must begin withFROM,ARG or comment.
DL4000ErrorMAINTAINER is deprecated.
DL4001WarningEither use Wget or Curl but not both.
DL4003WarningMultipleCMD instructions found.
DL4004ErrorMultipleENTRYPOINT instructions found.
DL4005WarningUseSHELL to change the default shell.
DL4006WarningSet theSHELL option -o pipefail beforeRUN with a pipe in it
SC1000$ is not used specially and should therefore be escaped.
SC1001This\c will be a regular'c' in this context.
SC1007Remove space after= if trying to assign a value (or for empty string, usevar='' ...).
SC1010Use semicolon or linefeed beforedone (or quote to make it literal).
SC1018This is a unicode non-breaking space. Delete it and retype as space.
SC1035You need a space here
SC1045It's notfoo &; bar, justfoo & bar.
SC1065Trying to declare parameters? Don't. Use() and refer to params as$1,$2 etc.
SC1066Don't use $ on the left side of assignments.
SC1068Don't put spaces around the= in assignments.
SC1077For command expansion, the tick should slant left (` vs ´).
SC1078Did you forget to close this double-quoted string?
SC1079This is actually an end quote, but due to next char, it looks suspect.
SC1081Scripts are case sensitive. Useif, notIf.
SC1083This{/} is literal. Check expression (missing;/\n?) or quote it.
SC1086Don't use$ on the iterator name in for loops.
SC1087Braces are required when expanding arrays, as in${array[idx]}.
SC1095You need a space or linefeed between the function name and body.
SC1097Unexpected==. For assignment, use=. For comparison, use[ .. ] or[[ .. ]].
SC1098Quote/escape special characters when usingeval, e.g.eval "a=(b)".
SC1099You need a space before the#.
SC2002Useless cat. Considercmd < file | .. orcmd file | .. instead.
SC2015Note thatA && B || C is not if-then-else. C may run when A is true.
SC2026This word is outside of quotes. Did you intend to 'nest '"'single quotes'"' instead'?
SC2028echo won't expand escape sequences. Considerprintf.
SC2035Use./*glob* or-- *glob* so names with dashes won't become options.
SC2039In POSIX sh, something is undefined.
SC2046Quote this to prevent word splitting
SC2086Double quote to prevent globbing and word splitting.
SC2140Word is in the form"A"B"C" (B indicated). Did you mean"ABC" or"A\"B\"C"?
SC2154var is referenced but not assigned.
SC2155Declare and assign separately to avoid masking return values.
SC2164Usecd ... || exit in casecd fails.

Develop

If you are an experienced Haskeller, we would be very grateful if you wouldtear our code apart in a review.

To compile, you will need a recent Haskell environment andcabal-install.

Setup

  1. Clone repository

    git clone --recursive git@github.com:hadolint/hadolint.git
  2. Install dependencies and compile source

    cabal configurecabal build
  3. (Optional) Install Hadolint on your system

    cabal install

REPL

The easiest way to try out the parser is using the REPL.

# start the replcabal repl# overload strings to be able to use Text:set -XOverloadedStrings# import parser libraryimport Language.Docker# parse instruction and look at AST representationparseText"FROM debian:jessie"

Tests

Compile with unit tests and run them:

cabal configure --enable-testscabal build --enable-testscabaltest

Run integration tests:

./integration_test.sh

AST

Dockerfile syntax is fully described in theDockerfile reference.Just take a look atSyntax.hs in thelanguage-docker project to seethe AST definition.

Building against custom libraries

Hadolint uses many libraries to do the dirty work. In particular,language-docker is used to parse Dockerfiles and produce an AST which then canbe analyzed. To build Hadolint against a custom version of such libraries, dothe following. This example uses language-docker, but it would work with anyother library as well.

  1. In the same directory (e.g./home/user/repos) clone Hadolint andlanguage-docker git repositories
cd /home/user/reposgit clone https://github.com/hadolint/hadolint.gitgit clone https://github.com/hadolint/language-docker.git
  1. Make your modifications to language-docker

  2. In the Hadolint repo, edit thecabal.project file, such that thepackages property points to the other repo too

[...]packages:.../language-docker[...]
  1. Recompile Hadolint and run the tests
cd /home/user/repos/hadolintcabal configure --enable-testscabal build --enable-testscabaltest

Alternatives


[8]ページ先頭

©2009-2025 Movatter.jp