[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-9979":3},{"id":4,"name":5,"fullName":6,"owner":5,"repo":5,"description":7,"homepage":8,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":15,"forks30d":15,"starsTrendScore":19,"compositeScore":20,"rankGlobal":9,"rankLanguage":9,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":24,"topics":25,"createdAt":9,"pushedAt":9,"updatedAt":33,"readmeContent":34,"aiSummary":35,"trendingCount":15,"starSnapshotCount":15,"syncStatus":36,"lastSyncTime":37,"discoverSource":38},9979,"hadolint","hadolint\u002Fhadolint","Dockerfile linter, validate inline bash, written in Haskell","",null,"Haskell",12209,496,67,211,0,3,22,85,20,43.09,"GNU General Public License v3.0",false,"master",true,[26,27,28,29,30,31,32],"docker","dockerfile","dockerfile-linter","haskell","linter","shellcheck","static-analysis","2026-06-12 02:02:15","# Hadolint - Haskell Dockerfile Linter\n\n[![GPL-3 licensed][license-img]][license]\n[![GitHub release][release-img]][release]\n[![Hackage version][hackage-img]][hackage]\n[![GitHub downloads][downloads-img]][release]\n[![Docker pulls][docker-img]][docker]\n[![Build Status][github-actions-img]][github-actions]\n\n\u003Cimg align=\"right\" alt=\"pipecat\" width=\"150\"\nsrc=\"https:\u002F\u002Fhadolint.github.io\u002Fhadolint\u002Fimg\u002Fcat_container.png\" \u002F>\n\nA smarter Dockerfile linter that helps you build [best practice][] Docker\nimages. The linter parses the Dockerfile into an AST and performs rules on\ntop of the AST. It stands on the shoulders of [ShellCheck][] to lint\nthe Bash code inside `RUN` instructions.\n\n[:globe_with_meridians: **Check the online version on\nhadolint.github.io\u002Fhadolint**](https:\u002F\u002Fhadolint.github.io\u002Fhadolint)\n[![Screenshot](screenshot.png)](https:\u002F\u002Fhadolint.github.io\u002Fhadolint)\n\n## Table of Contents\n\n- [How to use](#how-to-use)\n- [Install](#install)\n- [CLI](#cli)\n- [Configure](#configure)\n- [Non-Posix Shells](#non-posix-shells)\n- [Ignoring Rules](#ignoring-rules)\n  - [Inline ignores](#inline-ignores)\n  - [Global ignores](#global-ignores)\n- [Linting Labels](#linting-labels)\n  - [Note on dealing with variables in labels](#note-on-dealing-with-variables-in-labels)\n- [Integrations](#integrations)\n- [Rules](#rules)\n- [Develop](#develop)\n  - [Setup](#setup)\n  - [REPL](#repl)\n  - [Tests](#tests)\n  - [AST](#ast)\n  - [Building against custom libraries](#building-against-custom-libraries)\n- [Alternatives](#alternatives)\n\n## How to use\n\nYou can run `hadolint` locally to lint your Dockerfile.\n\n```bash\nhadolint \u003CDockerfile>\nhadolint --ignore DL3003 --ignore DL3006 \u003CDockerfile> # exclude specific rules\nhadolint --trusted-registry my-company.com:500 \u003CDockerfile> # Warn when using untrusted FROM images\n```\n\nDocker comes to the rescue, providing an easy way how to run `hadolint` on most\nplatforms.\nJust pipe your `Dockerfile` to `docker run`:\n\n```bash\ndocker run --rm -i hadolint\u002Fhadolint \u003C Dockerfile\n# OR\ndocker run --rm -i ghcr.io\u002Fhadolint\u002Fhadolint \u003C Dockerfile\n```\n\nor using [Podman](https:\u002F\u002Fpodman.io\u002F):\n\n```bash\npodman run --rm -i docker.io\u002Fhadolint\u002Fhadolint \u003C Dockerfile\n# OR\npodman run --rm -i ghcr.io\u002Fhadolint\u002Fhadolint \u003C Dockerfile\n```\n\nor using Windows PowerShell:\n\n```powershell\ncat .\\Dockerfile | docker run --rm -i hadolint\u002Fhadolint\n```\n\n## Install\n\nYou can download prebuilt binaries for OSX, Windows and Linux from the latest\n[release page][]. However, if this does not work for you, please fall back to\ncontainer (Docker), `brew` or source installation.\n\nOn OSX, you can use [brew](https:\u002F\u002Fbrew.sh\u002F) to install `hadolint`.\n\n```bash\nbrew install hadolint\n```\n\nOn Windows, you can use [scoop](https:\u002F\u002Fgithub.com\u002Flukesampson\u002Fscoop) to\ninstall `hadolint`.\n\n```batch\nscoop install hadolint\n```\n\nOn distributions that have `nix` installed, you can use the `hadolint`\npackage to run ad-hoc shells or permanently install `hadolint` into\nyour environment.\n\nAs mentioned earlier, `hadolint` is available as a container image:\n\n```bash\ndocker pull hadolint\u002Fhadolint\n# OR\ndocker pull ghcr.io\u002Fhadolint\u002Fhadolint\n```\n\nIf you need a container with shell access, use the Debian or Alpine\nvariants:\n\n```bash\ndocker pull hadolint\u002Fhadolint:latest-debian\n# OR\ndocker pull hadolint\u002Fhadolint:latest-alpine\n# OR\ndocker pull ghcr.io\u002Fhadolint\u002Fhadolint:latest-debian\n# OR\ndocker pull ghcr.io\u002Fhadolint\u002Fhadolint:latest-alpine\n```\n\nYou can also build `hadolint` locally. You need [Haskell][] and the [cabal][]\nbuild tool to build the binary.\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint \\\n  && cd hadolint \\\n  && cabal configure \\\n  && cabal build \\\n  && cabal install\n```\n\nIf you want the\n[VS Code Hadolint](https:\u002F\u002Fgithub.com\u002Fmichaellzc\u002Fvscode-hadolint)\nextension to use Hadolint in a container, you can use the following\n[wrapper script](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fissues\u002F691#issuecomment-932116329):\n\n```bash\n#!\u002Fbin\u002Fbash\ndockerfile=\"$1\"\nshift\ndocker run --rm -i hadolint\u002Fhadolint hadolint \"$@\" - \u003C \"$dockerfile\"\n```\n\n## CLI\n\n```bash\nhadolint --help\n```\n\n```text\nhadolint - Dockerfile Linter written in Haskell\n\nUsage: hadolint [-v|--version] [-c|--config FILENAME] [DOCKERFILE...]\n                [--file-path-in-report FILEPATHINREPORT] [--no-fail]\n                [--no-color] [-V|--verbose] [-f|--format ARG] [--error RULECODE]\n                [--warning RULECODE] [--info RULECODE] [--style RULECODE]\n                [--ignore RULECODE]\n                [--trusted-registry REGISTRY (e.g. docker.io)]\n                [--require-label LABELSCHEMA (e.g. maintainer:text)]\n                [--strict-labels] [--disable-ignore-pragma]\n                [-t|--failure-threshold THRESHOLD]\n  Lint Dockerfile for errors and best practices\n\nAvailable options:\n  -h,--help                Show this help text\n  -v,--version             Show version\n  -c,--config FILENAME     Path to the configuration file\n  --file-path-in-report FILEPATHINREPORT\n                           The file path referenced in the generated report.\n                           This only applies for the 'checkstyle', 'codeclimate',\n                           'sonarqube' and 'gitlab_codeclimate' formats and is\n                           useful when running Hadolint with Docker to set the\n                           correct file path.\n  --no-fail                Don't exit with a failure status code when any rule\n                           is violated\n  --no-color               Don't colorize output\n  -V,--verbose             Enables verbose logging of hadolint's output to\n                           stderr\n  -f,--format ARG          The output format for the results [tty | json |\n                           checkstyle | codeclimate | gitlab_codeclimate | gnu |\n                           codacy | sonarqube | sarif] (default: tty)\n  --error RULECODE         Make the rule `RULECODE` have the level `error`\n  --warning RULECODE       Make the rule `RULECODE` have the level `warning`\n  --info RULECODE          Make the rule `RULECODE` have the level `info`\n  --style RULECODE         Make the rule `RULECODE` have the level `style`\n  --ignore RULECODE        A rule to ignore. If present, the ignore list in the\n                           config file is ignored\n  --trusted-registry REGISTRY (e.g. docker.io)\n                           A docker registry to allow to appear in FROM\n                           instructions\n  --require-label LABELSCHEMA (e.g. maintainer:text)\n                           The option --require-label=label:format makes\n                           Hadolint check that the label `label` conforms to\n                           format requirement `format`\n  --strict-labels          Do not permit labels other than specified in\n                           `label-schema`\n  --disable-ignore-pragma  Disable inline ignore pragmas `# hadolint\n                           ignore=DLxxxx`\n  -t,--failure-threshold THRESHOLD\n                           Exit with failure code only when rules with a\n                           severity equal to or above THRESHOLD are violated.\n                           Accepted values: [error | warning | info | style |\n                           ignore | none] (default: info)\n```\n\n## Configure\n\nConfiguration files can be used globally or per project.\nHadolint looks for configuration files in the following locations or their\nplatform specific equivalents in this order and uses the first one exclusively:\n\n- `$PWD\u002F.hadolint.yaml`\n- `$XDG_CONFIG_HOME\u002Fhadolint.yaml`\n- `$HOME\u002F.config\u002Fhadolint.yaml`\n- `$HOME\u002F.hadolint\u002Fhadolint.yaml or $HOME\u002Fhadolint\u002Fconfig.yaml`\n- `$HOME\u002F.hadolint.yaml`\n\nIn windows, the `%LOCALAPPDATA%` environment variable is used instead of\n`XDG_CONFIG_HOME`. Config files can have either `yaml` or `yml` extensions.\n\n`hadolint` full `yaml` config file schema\n\n```yaml\nfailure-threshold: string               # name of threshold level (error | warning | info | style | ignore | none)\nformat: string                          # Output format (tty | json | checkstyle | codeclimate | gitlab_codeclimate | gnu | codacy)\nignored: [string]                       # list of rules\nlabel-schema:                           # See Linting Labels below for specific label-schema details\n  author: string                        # Your name\n  contact: string                       # email address\n  created: timestamp                    # rfc3339 datetime\n  version: string                       # semver\n  documentation: string                 # url\n  git-revision: string                  # hash\n  license: string                       # spdx\nno-color: boolean                       # true | false\nno-fail: boolean                        # true | false\noverride:\n  error: [string]                       # list of rules\n  warning: [string]                     # list of rules\n  info: [string]                        # list of rules\n  style: [string]                       # list of rules\nstrict-labels: boolean                  # true | false\ndisable-ignore-pragma: boolean          # true | false\ntrustedRegistries: string | [string]    # registry or list of registries\n```\n\n`hadolint` supports specifying the ignored rules using a configuration\nfile. The configuration file should be in `yaml` format. This is one\nvalid configuration file as an example:\n\n```yaml\nignored:\n  - DL3000\n  - SC1010\n```\n\nAdditionally, `hadolint` can warn you when images from untrusted\nrepositories are being used in Dockerfiles, you can append the\n`trustedRegistries` keys to the configuration file, as shown below:\n\n```yaml\nignored:\n  - DL3000\n  - SC1010\n\ntrustedRegistries:\n  - docker.io\n  - my-company.com:5000\n  - \"*.gcr.io\"\n```\n\nIf you want to override the severity of specific rules, you can do that too:\n\n```yaml\noverride:\n  error:\n    - DL3001\n    - DL3002\n  warning:\n    - DL3042\n    - DL3033\n  info:\n    - DL3032\n  style:\n    - DL3015\n```\n\n`failure-threshold` Exit with failure code only when rules with a\nseverity above THRESHOLD are violated (Available in v2.6.0+)\n\n```yaml\nfailure-threshold: info\noverride:\n  warning:\n    - DL3042\n    - DL3033\n  info:\n    - DL3032\n```\n\nAdditionally, you can pass a custom configuration file in the command line with\nthe `--config` option\n\n```bash\nhadolint --config \u002Fpath\u002Fto\u002Fconfig.yaml Dockerfile\n```\n\nTo pass a custom configuration file (using relative or absolute path) to\na container, use the following command:\n\n```bash\ndocker run --rm -i -v \u002Fyour\u002Fpath\u002Fto\u002Fhadolint.yaml:\u002F.config\u002Fhadolint.yaml hadolint\u002Fhadolint \u003C Dockerfile\n# OR\ndocker run --rm -i -v \u002Fyour\u002Fpath\u002Fto\u002Fhadolint.yaml:\u002F.config\u002Fhadolint.yaml ghcr.io\u002Fhadolint\u002Fhadolint \u003C Dockerfile\n```\n\nIn addition to config files, Hadolint can be configured with environment\nvariables.\n\n```bash\nNO_COLOR=1                               # Set or unset. See https:\u002F\u002Fno-color.org\nHADOLINT_NOFAIL=1                        # Truthy value e.g. 1, true or yes\nHADOLINT_VERBOSE=1                       # Truthy value e.g. 1, true or yes\nHADOLINT_FORMAT=json                     # Output format (tty | json | checkstyle | codeclimate | gitlab_codeclimate | gnu | codacy | sarif )\nHADOLINT_FAILURE_THRESHOLD=info          # threshold level (error | warning | info | style | ignore | none)\nHADOLINT_OVERRIDE_ERROR=DL3010,DL3020    # comma separated list of rule codes\nHADOLINT_OVERRIDE_WARNING=DL3010,DL3020  # comma separated list of rule codes\nHADOLINT_OVERRIDE_INFO=DL3010,DL3020     # comma separated list of rule codes\nHADOLINT_OVERRIDE_STYLE=DL3010,DL3020    # comma separated list of rule codes\nHADOLINT_IGNORE=DL3010,DL3020            # comma separated list of rule codes\nHADOLINT_STRICT_LABELS=1                 # Truthy value e.g. 1, true or yes\nHADOLINT_DISABLE_IGNORE_PRAGMA=1         # Truthy value e.g. 1, true or yes\nHADOLINT_TRUSTED_REGISTRIES=docker.io    # comma separated list of registry urls\nHADOLINT_REQUIRE_LABELS=maintainer:text  # comma separated list of label schema items\n```\n\n## Non-Posix Shells\n\nWhen using base images with non-posix shells as default (e.g. Windows based\nimages) a special pragma `hadolint shell` can specify which shell the base image\nuses, so that Hadolint can automatically ignore all shell-specific rules.\n\n```Dockerfile\nFROM mcr.microsoft.com\u002Fwindows\u002Fservercore:ltsc2022\n# hadolint shell=powershell\nRUN Get-Process notepad | Stop-Process\n```\n\n## Ignoring Rules\n\n### Inline ignores\n\nIt is also possible to ignore rules by adding a special comment directly\nabove the Dockerfile statement for which you want to make an exception for.\nSuch comments look like\n`# hadolint ignore=DL3001,SC1081`. For example:\n\n```dockerfile\n# hadolint ignore=DL3006\nFROM ubuntu\n\n# hadolint ignore=DL3003,SC1035 # We accept these issues, because ...\nRUN cd \u002Ftmp && echo \"hello!\"\n```\n\nThe comment \"inline ignores\" applies only to the statement following it.\n\nComments are allowed after the `ignore=...`, you need an extra `#`\n\n### Global ignores\n\nRules can also be ignored on a per-file basis using the global ignore pragma.\nIt works just like inline ignores, except that it applies to the whole file\ninstead of just the next line.\n\n```dockerfile\n# hadolint global ignore=DL3003,DL3006,SC1035 # We accept these issues, because ...\nFROM ubuntu\n\nRUN cd \u002Ftmp && echo \"foo\"\n```\n\n## Linting Labels\n\nHadolint is able to check if specific labels are present and conform\nto a predefined label schema.\nFirst, a label schema must be defined either via the command line:\n\n```bash\nhadolint --require-label author:text --require-label version:semver Dockerfile\n```\n\nor via the config file:\n\n```yaml\nlabel-schema:\n  author: text\n  contact: email\n  created: rfc3339\n  version: semver\n  documentation: url\n  git-revision: hash\n  license: spdx\n```\n\nThe value of a label can be either of `text`, `url`, `semver`, `hash` or\n`rfc3339`:\n\n| Schema  | Description                                        |\n|:--------|:---------------------------------------------------|\n| text    | Anything                                           |\n| rfc3339 | A time, formatted according to [RFC 3339][rfc3339] |\n| semver  | A [semantic version][semver]                       |\n| url     | A URI as described in [RFC 3986][rfc3986]          |\n| hash    | Either a short or a long [Git hash][githash]       |\n| spdx    | An [SPDX license identifier][spdxid]               |\n| email   | An email address conforming to [RFC 5322][rfc5322] |\n\nBy default, Hadolint ignores any label that is not specified in the label schema. To\nwarn against such additional labels, turn on strict labels, using the command line:\n\n```bash\nhadolint --strict-labels --require-label version:semver Dockerfile\n```\n\nor the config file:\n\n```yaml\nstrict-labels: true\n```\n\nWhen strict labels is enabled, but no label schema is specified, `hadolint`\nwill warn if any label is present.\n\n### Note on dealing with variables in labels\n\nIt is a common pattern to fill the value of a label not statically, but rather\ndynamically at build time by using a variable:\n\n```dockerfile\nFROM debian:buster\nARG VERSION=\"du-jour\"\nLABEL version=\"${VERSION}\"\n```\n\nTo allow this, the label schema must specify `text` as value for that label:\n\n```yaml\nlabel-schema:\n  version: text\n```\n\n## Integrations\n\nTo get most of `hadolint`, it is useful to integrate it as a check in your CI\nor into your editor, or as a pre-commit hook, to lint your `Dockerfile` as you\nwrite it. See our [Integration][] docs.\n\n- [Code Review Platform Integrations][]\n- [Continuous Integrations][]\n- [Editor Integrations][]\n- [Version Control Integrations][]\n\n## Rules\n\nAn incomplete list of implemented rules. Click on the error code to get more\ndetailed information.\n\n- Rules with the prefix `DL` are from `hadolint`. Have a look at\n    `Rules.hs` to find the implementation of the rules.\n\n- Rules with the `SC` prefix are from **ShellCheck** (only the most\n    common rules are listed, there are dozens more).\n\nPlease [create an issue][] if you have an idea for a good rule.\n\n\u003C!--lint disable maximum-line-length-->\n\n| Rule                                                         | Default Severity | Description                                                                                                                                         |\n|:-------------------------------------------------------------|:-----------------| :-------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [DL1001](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL1001)   | Ignore           | Please refrain from using inline ignore pragmas `# hadolint ignore=DLxxxx`.                                                                         |\n| [DL3000](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3000)   | Error            | Use absolute WORKDIR.                                                                                                                               |\n| [DL3001](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3001)   | Info             | 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. |\n| [DL3002](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3002)   | Warning          | Last user should not be root.                                                                                                                       |\n| [DL3003](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3003)   | Warning          | Use WORKDIR to switch to a directory.                                                                                                               |\n| [DL3004](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3004)   | Error            | Do not use sudo as it leads to unpredictable behavior. Use a tool like gosu to enforce root.                                                        |\n| [DL3006](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3006)   | Warning          | Always tag the version of an image explicitly.                                                                                                      |\n| [DL3007](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3007)   | Warning          | Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag.                                         |\n| [DL3008](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3008)   | Warning          | Pin versions in `apt-get install`.                                                                                                                  |\n| [DL3009](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3009)   | Info             | Delete the apt-get lists after installing something.                                                                                                |\n| [DL3010](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3010)   | Info             | Use ADD for extracting archives into an image.                                                                                                      |\n| [DL3011](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3011)   | Error            | Valid UNIX ports range from 0 to 65535.                                                                                                             |\n| [DL3012](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3012)   | Error            | Multiple `HEALTHCHECK` instructions.                                                                                                                |\n| [DL3013](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3013)   | Warning          | Pin versions in pip.                                                                                                                                |\n| [DL3014](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3014)   | Warning          | Use the `-y` switch.                                                                                                                                |\n| [DL3015](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3015)   | Info             | Avoid additional packages by specifying `--no-install-recommends`.                                                                                  |\n| [DL3016](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3016)   | Warning          | Pin versions in `npm`.                                                                                                                              |\n| [DL3018](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3018)   | Warning          | Pin versions in `apk add`. Instead of `apk add \u003Cpackage>` use `apk add \u003Cpackage>=\u003Cversion>`.                                                        |\n| [DL3019](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3019)   | Info             | Use the `--no-cache` switch to avoid the need to use `--update` and remove `\u002Fvar\u002Fcache\u002Fapk\u002F*` when done installing packages.                        |\n| [DL3020](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3020)   | Error            | Use `COPY` instead of `ADD` for files and folders.                                                                                                  |\n| [DL3021](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3021)   | Error            | `COPY` with more than 2 arguments requires the last argument to end with `\u002F`                                                                        |\n| [DL3022](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3022)   | Warning          | `COPY --from` should reference a previously defined `FROM` alias                                                                                    |\n| [DL3023](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3023)   | Error            | `COPY --from` cannot reference its own `FROM` alias                                                                                                 |\n| [DL3024](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3024)   | Error            | `FROM` aliases (stage names) must be unique                                                                                                         |\n| [DL3025](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3025)   | Warning          | Use arguments JSON notation for CMD and ENTRYPOINT arguments                                                                                        |\n| [DL3026](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3026)   | Error            | Use only an allowed registry in the `FROM image`                                                                                                    |\n| [DL3027](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3027)   | Warning          | Do not use `apt` as it is meant to be an end-user tool, use `apt-get` or `apt-cache` instead                                                        |\n| [DL3028](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3028)   | Warning          | Pin versions in gem install. Instead of `gem install \u003Cgem>` use `gem install \u003Cgem>:\u003Cversion>`                                                       |\n| [DL3029](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3029)   | Warning          | Do not use --platform flag with FROM.                                                                                                               |\n| [DL3030](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3030)   | Warning          | Use the `-y` switch to avoid manual input `yum install -y \u003Cpackage>`                                                                                |\n| [DL3032](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3032)   | Warning          | `yum clean all` missing after yum command.                                                                                                          |\n| [DL3033](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3033)   | Warning          | Specify version with `yum install -y \u003Cpackage>-\u003Cversion>`                                                                                           |\n| [DL3034](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3034)   | Warning          | Non-interactive switch missing from `zypper` command: `zypper install -y`                                                                           |\n| [DL3035](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3035)   | Warning          | Do not use `zypper dist-upgrade`.                                                                                                                   |\n| [DL3036](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3036)   | Warning          | `zypper clean` missing after zypper use.                                                                                                            |\n| [DL3037](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3037)   | Warning          | Specify version with `zypper install -y \u003Cpackage>[=]\u003Cversion>`.                                                                                     |\n| [DL3038](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3038)   | Warning          | Use the `-y` switch to avoid manual input `dnf install -y \u003Cpackage>`                                                                                |\n| [DL3040](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3040)   | Warning          | `dnf clean all` missing after dnf command.                                                                                                          |\n| [DL3041](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3041)   | Warning          | Specify version with `dnf install -y \u003Cpackage>-\u003Cversion>`                                                                                           |\n| [DL3042](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3042)   | Warning          | Avoid cache directory with `pip install --no-cache-dir \u003Cpackage>`.                                                                                  |\n| [DL3043](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3043)   | Error            | `ONBUILD`, `FROM` or `MAINTAINER` triggered from within `ONBUILD` instruction.                                                                      |\n| [DL3044](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3044)   | Error            | Do not refer to an environment variable within the same `ENV` statement where it is defined.                                                        |\n| [DL3045](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3045)   | Warning          | `COPY` to a relative destination without `WORKDIR` set.                                                                                             |\n| [DL3046](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3046)   | Warning          | `useradd` without flag `-l` and high UID will result in excessively large Image.                                                                    |\n| [DL3047](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3047)   | Info             | `wget` without flag `--progress` will result in excessively bloated build logs when downloading larger files.                                       |\n| [DL3048](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3048)   | Style            | Invalid Label Key                                                                                                                                   |\n| [DL3049](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3049)   | Info             | Label `\u003Clabel>` is missing.                                                                                                                         |\n| [DL3050](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3050)   | Info             | Superfluous label(s) present.                                                                                                                       |\n| [DL3051](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3051)   | Warning          | Label `\u003Clabel>` is empty.                                                                                                                           |\n| [DL3052](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3052)   | Warning          | Label `\u003Clabel>` is not a valid URL.                                                                                                                 |\n| [DL3053](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3053)   | Warning          | Label `\u003Clabel>` is not a valid time format - must conform to RFC3339.                                                                               |\n| [DL3054](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3054)   | Warning          | Label `\u003Clabel>` is not a valid SPDX license identifier.                                                                                             |\n| [DL3055](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3055)   | Warning          | Label `\u003Clabel>` is not a valid git hash.                                                                                                            |\n| [DL3056](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3056)   | Warning          | Label `\u003Clabel>` does not conform to semantic versioning.                                                                                            |\n| [DL3057](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3057)   | Ignore           | `HEALTHCHECK` instruction missing.                                                                                                                  |\n| [DL3058](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3058)   | Warning          | Label `\u003Clabel>` is not a valid email format - must conform to RFC5322.                                                                              |\n| [DL3059](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3059)   | Info             | Multiple consecutive `RUN` instructions. Consider consolidation.                                                                                    |\n| [DL3060](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3060)   | Info             | `yarn cache clean` missing after `yarn install` was run.                                                                                            |\n| [DL3061](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3061)   | Error            | Invalid instruction order. Dockerfile must begin with `FROM`, `ARG` or comment.                                                                     |\n| [DL3062](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3062)   | Warning          | Pin versions in go install. Instead of `go install \u003Cpackage>` use `go install \u003Cpackage>@\u003Cversion>`                                                  |\n| [DL3063](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL3063)   | Warning          | Stage name should not be a reserved word                                                                                                            |\n| [DL4000](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL4000)   | Error            | `MAINTAINER` is deprecated.                                                                                                                         |\n| [DL4001](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL4001)   | Warning          | Either use Wget or Curl but not both.                                                                                                               |\n| [DL4003](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL4003)   | Warning          | Multiple `CMD` instructions found.                                                                                                                  |\n| [DL4004](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL4004)   | Error            | Multiple `ENTRYPOINT` instructions found.                                                                                                           |\n| [DL4005](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL4005)   | Warning          | Use `SHELL` to change the default shell.                                                                                                            |\n| [DL4006](https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fwiki\u002FDL4006)   | Warning          | Set the `SHELL` option -o pipefail before `RUN` with a pipe in it                                                                                   |\n| [SC1000](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1000) |                  | `$` is not used specially and should therefore be escaped.                                                                                          |\n| [SC1001](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1001) |                  | This `\\c` will be a regular `'c'` in this context.                                                                                                  |\n| [SC1007](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1007) |                  | Remove space after `=` if trying to assign a value (or for empty string, use `var='' ...`).                                                         |\n| [SC1010](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1010) |                  | Use semicolon or linefeed before `done` (or quote to make it literal).                                                                              |\n| [SC1018](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1018) |                  | This is a unicode non-breaking space. Delete it and retype as space.                                                                                |\n| [SC1035](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1035) |                  | You need a space here                                                                                                                               |\n| [SC1045](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1045) |                  | It's not `foo &; bar`, just `foo & bar`.                                                                                                            |\n| [SC1065](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1065) |                  | Trying to declare parameters? Don't. Use `()` and refer to params as `$1`, `$2` etc.                                                                |\n| [SC1066](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1066) |                  | Don't use $ on the left side of assignments.                                                                                                        |\n| [SC1068](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1068) |                  | Don't put spaces around the `=` in assignments.                                                                                                     |\n| [SC1077](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1077) |                  | For command expansion, the tick should slant left (\\` vs ´).                                                                                        |\n| [SC1078](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1078) |                  | Did you forget to close this double-quoted string?                                                                                                  |\n| [SC1079](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1079) |                  | This is actually an end quote, but due to next char, it looks suspect.                                                                              |\n| [SC1081](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1081) |                  | Scripts are case sensitive. Use `if`, not `If`.                                                                                                     |\n| [SC1083](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1083) |                  | This `{\u002F}` is literal. Check expression (missing `;\u002F\\n`?) or quote it.                                                                              |\n| [SC1086](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1086) |                  | Don't use `$` on the iterator name in for loops.                                                                                                    |\n| [SC1087](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1087) |                  | Braces are required when expanding arrays, as in `${array[idx]}`.                                                                                   |\n| [SC1091](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1091) |                  | Not following: Reasons include: file not found, no permissions, not included on the command line, not allowing shellcheck to follow files with -x, etc. |\n| [SC1095](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1095) |                  | You need a space or linefeed between the function name and body.                                                                                    |\n| [SC1097](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1097) |                  | Unexpected `==`. For assignment, use `=`. For comparison, use `[ .. ]` or `[[ .. ]]`.                                                               |\n| [SC1098](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1098) |                  | Quote\u002Fescape special characters when using `eval`, e.g. `eval \"a=(b)\"`.                                                                             |\n| [SC1099](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC1099) |                  | You need a space before the `#`.                                                                                                                    |\n| [SC2002](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2002) |                  | Useless cat. Consider \u003Ccode>cmd \u003C file &#124; ..\u003C\u002Fcode> or \u003Ccode>cmd file &#124; ..\u003C\u002Fcode> instead.                                                 |\n| [SC2015](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2015) |                  | Note that \u003Ccode>A && B &#124;&#124; C\u003C\u002Fcode> is not if-then-else. C may run when A is true.                                                         |\n| [SC2026](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2026) |                  | This word is outside of quotes. Did you intend to 'nest '\"'single quotes'\"' instead'?                                                               |\n| [SC2028](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2028) |                  | `echo` won't expand escape sequences. Consider `printf`.                                                                                            |\n| [SC2035](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2035) |                  | Use `.\u002F*glob*` or `-- *glob*` so names with dashes won't become options.                                                                            |\n| [SC2039](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2039) |                  | In POSIX sh, something is undefined.                                                                                                                |\n| [SC2046](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2046) |                  | Quote this to prevent word splitting                                                                                                                |\n| [SC2086](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2086) |                  | Double quote to prevent globbing and word splitting.                                                                                                |\n| [SC2140](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2140) |                  | Word is in the form `\"A\"B\"C\"` (B indicated). Did you mean `\"ABC\"` or `\"A\\\"B\\\"C\"`?                                                                   |\n| [SC2154](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2154) |                  | var is referenced but not assigned.                                                                                                                 |\n| [SC2155](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2155) |                  | Declare and assign separately to avoid masking return values.                                                                                       |\n| [SC2164](https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\u002Fwiki\u002FSC2164) |                  | Use \u003Ccode>cd ... &#124;&#124; exit\u003C\u002Fcode> in case `cd` fails.                                                                                       |\n\n\u003C!--lint enable maximum-line-length-->\n\n## Develop\n\nIf you are an experienced Haskeller, we would be very grateful if you would\ntear our code apart in a review.\n\nTo compile, you will need a recent Haskell environment and `cabal-install`.\n\n### Setup\n\n1. Clone repository\n\n    ```bash\n    git clone --recursive git@github.com:hadolint\u002Fhadolint.git\n    ```\n\n1. Install dependencies and compile source\n\n    ```bash\n    cabal configure\n    cabal update\n    cabal build\n    ```\n\n1. (Optional) Install Hadolint on your system\n\n    ```bash\n    cabal install\n    ```\n\n### REPL\n\nThe easiest way to try out the parser is using the REPL.\n\n```bash\n# start the repl\ncabal repl\n# overload strings to be able to use Text\n:set -XOverloadedStrings\n# import parser library\nimport Language.Docker\n# parse instruction and look at AST representation\nparseText \"FROM debian:jessie\"\n```\n\n### Tests\n\nCompile with unit tests and run them:\n\n```bash\ncabal configure --enable-tests\ncabal build --enable-tests\ncabal test\n```\n\nRun integration tests:\n\n```bash\n.\u002Fintegration_test.sh\n```\n\n### AST\n\nDockerfile syntax is fully described in the [Dockerfile reference][].\nJust take a look at [Syntax.hs][] in the `language-docker` project to see\nthe AST definition.\n\n### Building against custom libraries\n\nHadolint uses many libraries to do the dirty work. In particular,\nlanguage-docker is used to parse Dockerfiles and produce an AST which then can\nbe analyzed. To build Hadolint against a custom version of such libraries, do\nthe following. This example uses language-docker, but it would work with any\nother library as well.\n\n 1) In the same directory (e.g. `\u002Fhome\u002Fuser\u002Frepos`) clone Hadolint and\n    language-docker git repositories\n\n```bash\ncd \u002Fhome\u002Fuser\u002Frepos\ngit clone https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint.git\ngit clone https:\u002F\u002Fgithub.com\u002Fhadolint\u002Flanguage-docker.git\n```\n\n 2) Make your modifications to language-docker\n\n 3) In the Hadolint repo, edit the `cabal.project` file, such that the\n    `packages` property points to the other repo too\n\n```yaml\n[...]\npackages:\n  .\n  ..\u002Flanguage-docker\n[...]\n```\n\n 4) Recompile Hadolint and run the tests\n\n```bash\ncd \u002Fhome\u002Fuser\u002Frepos\u002Fhadolint\ncabal configure --enable-tests\ncabal build --enable-tests\ncabal test\n```\n\n## Alternatives\n\n- replicatedhq\u002F[dockerfilelint](https:\u002F\u002Fgithub.com\u002Freplicatedhq\u002Fdockerfilelint),\n    the other linter used by the [super-linter](https:\u002F\u002Fgithub.com\u002Fgithub\u002Fsuper-linter\u002Fblob\u002Fmain\u002FREADME.md#supported-linters)\n\n- RedCoolBeans\u002F[dockerlint](https:\u002F\u002Fgithub.com\u002FRedCoolBeans\u002Fdockerlint\u002F)\n\n- projectatomic\u002F[dockerfile_lint](https:\u002F\u002Fgithub.com\u002Fprojectatomic\u002Fdockerfile_lint\u002F)\n\n\u003C!-- References -->\n\n[github-actions-img]: https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Factions\u002Fworkflows\u002Fhaskell.yml\u002Fbadge.svg?branch=master\n[github-actions]: https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Factions\u002Fworkflows\u002Fhaskell.yml\n[license-img]: https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-GPL--3-blue.svg\n[license]: https:\u002F\u002Ftldrlegal.com\u002Fl\u002Fgpl-3.0\n[release-img]: https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Frelease\u002Fhadolint\u002Fhadolint?logo=github\n[release-date]: https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Frelease-date\u002Fhadolint\u002Fhadolint?logo=github\n[release]: https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Freleases\u002Flatest\n[docker]: https:\u002F\u002Fhub.docker.com\u002Fr\u002Fhadolint\u002Fhadolint\n[hackage]: https:\u002F\u002Fhackage.haskell.org\u002Fpackage\u002Fhadolint\n[downloads-img]: https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fdownloads\u002Fhadolint\u002Fhadolint\u002Ftotal?logo=github\n[hackage-img]: https:\u002F\u002Fimg.shields.io\u002Fhackage\u002Fv\u002Fhadolint?logo=haskell\n[docker-img]: https:\u002F\u002Fimg.shields.io\u002Fdocker\u002Fpulls\u002Fhadolint\u002Fhadolint?logo=docker\n[best practice]: https:\u002F\u002Fdocs.docker.com\u002Fengine\u002Fuserguide\u002Feng-image\u002Fdockerfile_best-practices\n[shellcheck]: https:\u002F\u002Fgithub.com\u002Fkoalaman\u002Fshellcheck\n[release page]: https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Freleases\u002Flatest\n[haskell]: https:\u002F\u002Fwww.haskell.org\u002Fdownloads\u002F\n[cabal]: https:\u002F\u002Fwww.haskell.org\u002Fcabal\u002F\n[integration]: docs\u002FINTEGRATION.md\n[code review platform integrations]: docs\u002FINTEGRATION.md#code-review\n[continuous integrations]: docs\u002FINTEGRATION.md#continuous-integration\n[editor integrations]: docs\u002FINTEGRATION.md#editors\n[version control integrations]: docs\u002FINTEGRATION.md#version-control\n[create an issue]: https:\u002F\u002Fgithub.com\u002Fhadolint\u002Fhadolint\u002Fissues\u002Fnew\n[dockerfile reference]: http:\u002F\u002Fdocs.docker.com\u002Fengine\u002Freference\u002Fbuilder\u002F\n[syntax.hs]: https:\u002F\u002Fwww.stackage.org\u002Fhaddock\u002Fnightly-2022-11-15\u002Flanguage-docker-12.0.0\u002FLanguage-Docker-Syntax.html\n[rfc3339]: https:\u002F\u002Fwww.ietf.org\u002Frfc\u002Frfc3339.txt\n[semver]: https:\u002F\u002Fsemver.org\u002F\n[rfc3986]: https:\u002F\u002Fwww.ietf.org\u002Frfc\u002Frfc3986.txt\n[githash]: https:\u002F\u002Fgit-scm.com\u002Fbook\u002Fen\u002Fv2\u002FGit-Tools-Revision-Selection\n[spdxid]: https:\u002F\u002Fspdx.org\u002Flicenses\u002F\n[rfc5322]: https:\u002F\u002Fwww.ietf.org\u002Frfc\u002Frfc5322.txt\n","Hadolint 是一个用于 Dockerfile 的智能代码检查工具，使用 Haskell 语言编写。它能够解析 Dockerfile 并基于抽象语法树执行规则检查，同时利用 ShellCheck 对 RUN 指令中的 Bash 代码进行静态分析。该工具支持多种安装方式，包括预编译二进制文件、Docker 容器以及通过包管理器如 Homebrew 或 Scoop 安装。用户还可以自定义忽略特定的检查规则。Hadolint 非常适合需要确保 Docker 镜像构建遵循最佳实践的开发者或团队，在持续集成\u002F持续部署（CI\u002FCD）流程中尤为有用。",2,"2026-06-11 03:25:56","top_topic"]