GithubHelp home page GithubHelp logo

replicatedhq / dockerfilelint Goto Github PK

View Code? Open in Web Editor NEW
969.0 23.0 84.0 420 KB

An opinionated Dockerfile linter.

Home Page: https://www.fromlatest.io

License: MIT License

JavaScript 99.53% Dockerfile 0.47%
dockerfile linter

dockerfilelint's People

Contributors

alecjacobs5401 avatar alexbeggs avatar asears avatar bettiolo avatar bueller avatar dansnow avatar deiga avatar dependabot[bot] avatar drewfreyling avatar egoexpress avatar emosbaugh avatar greenkeeperio-bot avatar jwiebalk avatar marccampbell avatar nexdrew avatar o5 avatar sameetn avatar sboschman avatar sethbergman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dockerfilelint's Issues

RUN: All chained commands should be parsed

RUN apk update \
  && apk add ca-certificates \ 
  && rm -rf /var/cache/apk/*

=> "Consider --no-cache or --update with rm -rf /var/cache/apk/* (Optimization)"

The parser should detect the rm -rf … in the third line.

RUN apk update \
  && rm -rf /var/cache/apk/*

=> No error message.

apt-get --no-install-recommends

The --no-install-recommends is not found in case something like this is used:
apt-get -y install perl --no-install-recommends

`fromlatest.io` still errors on having `ARG` before `FROM`

Currently, the linter gives warning of 'First Command Must Be FROM (Possible Bug)'. However, I think there is at least one exception:

In order to have access to build arguments in multiple stages, said build arguments should be declared in the outer scope of the Dockerfile, before any FROM directives

Unexpected token ILLEGAL

I think I'm following the instructions, but I'm getting the following error:

$ ./bin/dockerfilelint ../docker/Dockerfile
E:\dockerfilelint\lib\reference.js:4
    'description': `All commands in a Dockerfile require at least 1 argument.
                   ^
SyntaxError: Unexpected token ILLEGAL
    at exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:443:25)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (E:\dockerfilelint\lib\messages.js:2:17)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)

Running from Cygwin.

Add version command line option

Most users expect there to be a version cli option for most apps. Dockerfilelint does not have a version cli option so I propose we add one.

I could simply just read the version declared in the package.json file.

EXPOSE ports not analysed correctly

In the docker expose instruction one can define what protocol too.

e.g.
EXPOSE 80/tcp 3000/udp

This is currently detected as a non valid port. Definition of the protocol is allowed.

This is maybe fixed by that:

  expose_port_valid: function(port) {
    return /^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\/tcp|\/udp){0,1}$/.test(port);
  },

This also checks for a valid port in range, since currently 99999999 is also detected as a valid port.

License of dockerfilelint unclear

According to the package.json file, the project appears to be under the MIT license.

"license": "MIT",

I'm not sure if this is accurate or just a copy/paste thing. I think a license file should be added to the root of the Git repository to disambiguate the licensing terms and use of this project and its source code.

Add more detailed explanations on the reasons why sudo should be avoided

If sudo is included in a command, dockerfilelint outputs the following message:

Avoid installing or using sudo since it has unpredictable TTY and signal-forwarding behavior that can cause problems. If you absolutely need functionality similar to sudo, such as initializing the daemon as root but running it as non-root), consider using “gosu”.

This message should give more detailed explanations (or a link) on the reasons why sudo should be avoided.

There is also a question about this on unix.stackexchange.com : What exactly in the sudo behavior is unpredictable?

Label Is Invalid when spaces in label

When the label value contains spaces, the "Label Is Invalid" check breaks down:

File:   <stdin>
Issues: 1
Line 41: LABEL build_user_on_behalf_of="Sander\ Verhagen"
Issue  Category      Title                 Description
    1  Possible Bug  Label Is Invalid      Using LABEL should be in key=value format.

Doesn't detect use of 'latest' or missing tag

The following FROM definitions should all trigger a message:

FROM some.registry:1234/repo/image
FROM some.registry:1234/repo/image as example

FROM repo/image:latest as example
FROM some.registry/repo/image:latest as example
FROM some.registry:1234/repo/image:latest
FROM some.registry:1234/repo/image:latest as example

The presence of the port number for the registry and the use of as seems to cause the parser to not catch the missing tag or use of latest.

Add support for ENV $VAR; EXPOSE $VAR pattern

This pattern allows us to define a variable and then re-use it in multiple areas in order to keep our Dockerfile DRY. Under the current implementation; dockerfilelint will state "Invalid Port Exposed"

Somewhat related to #78.

Line 14 apt-get update without matching apt-get install

I've got this error message:

˙Line 14 apt-get update without matching apt-get install

All instances of apt-get update should have the apt-get install commands on the same line to reduce image size.

For the following command:

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests \
    curl

YError: Invalid first argument. Expected boolean or string but received function.

I'm seeing this with the latest version of dockerfilelint. Running it from the command line or from a container. If I pull a container that's 4 months old I don't see this issue.

./bin/dockerfilelint /Users/cschlit/docker/java/Dockerfile.generated
YError: Invalid first argument. Expected boolean or string but received function.
at argumentTypeError (/Users/cschlit/temp/dockerfilelint/node_modules/yargs/lib/argsert.js:67:9)
at parsed.optional.forEach (/Users/cschlit/temp/dockerfilelint/node_modules/yargs/lib/argsert.js:49:39)
at Array.forEach ()
at argsert (/Users/cschlit/temp/dockerfilelint/node_modules/yargs/lib/argsert.js:44:21)
at Object.version (/Users/cschlit/temp/dockerfilelint/node_modules/yargs/yargs.js:790:5)
at Object. (/Users/cschlit/temp/dockerfilelint/bin/dockerfilelint:21:4)
at Module._compile (internal/modules/cjs/loader.js:722:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:733:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)

File: /Users/cschlit/docker/java/Dockerfile.generated
Issues: None found 👍

Going back to this version (be1f746) on the container on dockerhub - I don't see this issue.

It looks like it's running through the testing correctly, but with that message coming up every time I run it, it looks like it's not working correctly.

Extra USER arguments are not ignored even though dockerfilelint claims they are

FROM alpine
USER root node
$ docker run -v `pwd`/Dockerfile:/Dockerfile replicated/dockerfilelint /Dockerfile

File:   /Dockerfile
Issues: 2

Line 1: FROM alpine
Issue  Category      Title                 Description
    1  Clarity       Base Image Missing    Base images should specify a tag to use.
                     Tag

Line 2: USER root node
Issue  Category      Title                 Description
    2  Possible Bug  Extra Arguments       This command has extra arguments and will be ignored.
$ docker run -it test
docker: Error response from daemon: linux spec user: unable to find user root node: no matching entries in passwd file.

Add the ability to pass a config object instead of configPath to dockerfilelint.run()

I am trying to use Dockerfilelint programmatically.
dockerfilelint.run() rereads a config using fs.lstatSync() and fs.readFileSync() on every call.
It would be more performant (and in my case more convenient) to be able to pass a config object instead of configPath to dockerfilelint.run():

// I already have `configObject` and `files`
const warnings = files.map(
    // Here `dockerfilelint.run()` doesn't read anything from filesystem
    (content) => dockerfilelint.run(configObject, content)
);

Wrong Message

If I try to lint this Dockerfile that starts with the followinf two layer declaratio:

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80

FROM microsoft/dotnet:2.1-sdk AS publish

I get a suggestion that the first line should be a FROM. And actually it is.

Skip checks

Is it possible to skip selected "rules"? We have a few rules that we find acceptable, despite not being a best practice and it would be nice to silence those.

Should linter raise error if no file found?

If I run linter with filename which does not exist it just gives me normal output with 4 issues.

Command:

dockerfilelint NotExistingDockerfile

Output:

File:   <contents>
Issues: 4

Line 1: NotExistingDockerfile
Issue  Category      Title                 Description
    1  Possible Bug  Missing Required      All commands in a Dockerfile require at least 1 argument.
                     Arguments             A line in a Dockerfile can be in any of the following formats:
                                           * * *
                                           #### `# Comment`
                                           Docker will treat any line that begins with a `#` as a comment.
                                           * * *
                                           #### `INSTRUCTION arguments`
                                           All instructions require at least 1 argument, and should be on the
                                           same line as the `INSTRUCTION`.
                                           * * *
                                           #### `RUN` continuation
                                           If a `RUN` line ends with a `\`, the next line will be treated as
                                           part of the same `RUN` arguement.
                                           * * *
                                           #### Blank or Whitespace
                                           Blank lines are allowed and will be ignored.
                                           * * *
    2  Clarity       Capitalize            For clarity and readability, all instructions in a Dockerfile
                     Dockerfile            should be uppercase.
                     Instructions          This is a convention adopted by most of the official images and
                                           greatly improves readability in long Dockerfiles.  For an example
                                           of
                                           why this makes a difference, check out the current [redis
                                           Dockerfile](https://github.com/docker-library/redis/blob/b375650fb6
                                           9b7db819e90c0033433c705b28656e/3.0/Dockerfile)
                                           and you should be able to easily see the instructions used.
    3  Possible Bug  First Command Must    The first instruction in a Dockerfile must specify the base image
                     Be FROM               using a FROM command.  Additionally, FROM cannot appear later in a
                                           Dockerfile.
    4  Possible Bug  Invalid Line          This line is not a valid Dockerfile line.

Should linter report internal errors such as it is to stderr?
Something like File NotExistingDockerfile not found

Linting of stdin?

Would it be acceptable to allow for linting stdin somehow? (so this could lint the output of some other tool more easily)

The workarounds I tried failed in pretty amusing ways:

$ echo 'FROM scratch' | dockerfilelint -
File not found
$ echo 'FROM scratch' | dockerfilelint /dev/stdin
Argument should be a file
$ dockerfilelint <(echo 'FROM scratch')
Argument should be a file

False Positive --virtual

FROM ruby:2.3-alpine
MAINTAINER 8gears AG <hello.at.8gears.com>

WORKDIR /
COPY . /

EXPOSE 80 443

RUN apk --no-cache add -q -U --virtual build-dependencies \
    gcc g++ make musl-dev openssl-dev libffi-dev curl-dev mariadb-dev libxml2-dev zlib-dev libgcrypt-dev libxslt-dev coreutils\
    && apk --no-cache add bash zlib libcurl libxslt tzdata mariadb-libs mariadb-client-libs nodejs\
    && echo 'gem: --verbose --no-document' > /etc/gemrc \
    && gem update --no-document --quiet --system \
    && bundle config build.nokogiri --use-system-libraries \
    && bundle install --jobs=`nproc` --retry=3 --no-cache --clean \
    && rake assets:precompile && rake webpack:compile \
    && apk del --purge build-dependencies ; bash -c "rm -rf /{tmp,root}/{*,.??*}" \
    && rm -rf /usr/lib/ruby/gems/*/cache/* /var/cache/apk/*

COPY . /
ADD . . 

CMD ["/start.sh"]


It says I should use --virtualhowever I do use it but in the second apk statement the first one is fine as is.

Option for JSON output

I would love to use this project in our Jenkins build pipeline. Having the ability to output JSON would be extremely useful!

Suggest merging multiple env directives into one

As documentation describes, using merged form of ENV directives is preferred over the single form since it will yield smaller intermediate layers and containers.

Hence suggesting changing

ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy

to

ENV myName="John Doe" \
    myDog="Rex The Dog" \
    myCat="fluffy"

seems reasonable.

Should base image tag be linted for `latest`

Hi,

I was experimenting with linting some dockerfiles and noticed for multi-stage builds the base image we use generally as a builder, does not get linted for the :latest tag. Is this intentional?

For Example:

FROM golang:latest as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
RUN apk add ca-certificates
WORKDIR /root/
copy --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]

The second FROM gets the warning, but the first does not.

Thanks

Glob pattern or directory as source

Add a feature to specify a glob pattern instead of single file as input or directory with recursive search for Dockerfiles.
I have a project with many dockerfiles in special directory and I want to lint them all, ideally with glob pattern I will do something like this

$ docker run -v `pwd`/docker:/docker replicated/dockerfilelint /docker/**/Dockerfile

or specify a directory like this for search all Dockerfiles inside

$ docker run -v `pwd`/docker:/docker replicated/dockerfilelint /docker/

FROM errors with --platform arg

When using the --platform arg to the FROM directive in a Dockerfile, dockerfilelint errors saying it should specify a tag.

i.e.

Line 7: FROM --platform=$BUILDPLATFORM golang:alpine3.12 as test
Issue  Category      Title                 Description
    1  Clarity       Base Image Missing    Base images should specify a tag to use.
                     Tag

I tested just taking out the --platform=$BUILDPLATFORM part and it doesn't error any more.

Let me know if you need any more info.

ref:
https://docs.docker.com/engine/reference/builder/#from

Warning at multistage build

Gives next warnings dockerfilelint:
15:1 warning dockerfilelint: Clarity Base images should specify a tag to use.
21:1 warning dockerfilelint: Clarity Base images should specify a tag to use.
26:1 warning dockerfilelint: Clarity Base images should specify a tag to use.

Where should I put this tag?

# docker --host=:3000 build -t spa .

# ---- Base image ----
FROM node:alpine AS base

LABEL version="1.0"
LABEL description="HRketing SPA application"
LABEL maintainer="Alex Kostyukov <[email protected]>"

RUN apk --no-cache --update add git
WORKDIR /usr/src/deps
COPY package*.json ./

# ---- Dependencies ----
FROM base AS dependencies
RUN npm set progress=false && npm config set depth 0
RUN npm install --loglevel=error --only=production --prefix node_modules_production
RUN npm install --loglevel=error

# ---- Linters ----
FROM dependencies AS test
COPY . .
RUN npm run lint

# ---- Release ----
FROM base AS release

ARG NODE_ENV=production
ENV NODE_ENV=$NODE_ENV

WORKDIR /usr/src/app
COPY --from=dependencies /usr/src/deps/node_modules_production ./node_modules
COPY . .
EXPOSE 3000
CMD ["npm", "run", "deploy"]

dockerfilelint should not recommend against installing security updates by default

I have to disable apt-get-upgrade and apt-get-dist-upgrade on every project because those steps are mandatory for installing security updates. The referenced blog post is now gone but the reasoning was always highly suspect for anyone who cares about security since it basically says “don't patch your systems, just get used to ignoring all of those CVEs until you can get an upstream update shipped”. Due to the way layers work, if the upstream is responsive the update will have minimal impact on the image size since all of the relevant packages will already be installed so the only time this has a significant impact is precisely when you need it for security and reliability reasons.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.