← All posts
CloudFormation

Automatically updated docker image for cfn-lint

If you’re using CloudFormation, you probably know about cfn-lint - a linting tool created by the CloudFormation team to validate templates against the schema and best practices. Validating each template before deployment is in itself actually considered a best practice by AWS. However, simply using validate-template in the Console or CLI only validates the basic syntax of the template, not the actual contents and resource specification. That’s where using a linter like cfn-lint can be helpful to make sure you’re not making any obvious mistakes or going against best practices in your resources.

You can use cfn-lint in a number of ways during development, including simply within command-line, using git pre-commit hooks or as a plugin to your IDE. All those options, while helpful in day-to-day work, do not establish code quality standards for your overall codebase. To do that, it’s ideal to include linting as part of CI/CD pipeline and/or pull/merge-requests approval process.

That is where you can come across a hurdle: cfn-lint does not have an official, up-to-date docker image

The issue

Most automated build processes use docker to provide variety of tools and services for validation and testing. Lack of a reliable, up-to-date docker image for cfn-lint definitely inhibits wider adoption of the tool. This specific issue has been open on GitHub since 2019, and unfortunately there has been no indication from the CloudFormation team that there is a will to resolve it. While cfn-lint repository does contain a Dockerfile - you’d need to maintain your own copy of the image and update it regularly when the releases become available. That’s obviously going to be too much of a hassle for most companies just for a simple linting tool. You can find a number of images on Docker Hub that claim to provide this software, but vast majority seems to have been abandoned (published once by an eager person who stumbled upon this exact issue) or contain very little information about usage or transparency (and so, its safety).

The solution

To help with this predicament, we have created (yet another) repository with a Docker image for cfn-lint - but this one is different.

Here’s how:

  1. The image is automatically updated by using GitHub Actions scheduled to check daily if a new cfn-lint release is available. So you can be sure that using :latest tag, actually gives you the latest version.
  2. The repository is 100% transparent and public - you can see all the steps that are used to build the image. The Dockerfile used by the build is part of the repo, so you can see how it’s built - we do not modify any code and the only software installed. is cfn-lint. So you can be sure it’s safe, as intended by the creators.
  3. The repository will not become abandoned or broken - thanks to the automation, there’s nothing to abandon. As long as the Dockerfile within cfn-lint repository works, our build process will work and continue producing images for your use.

You can find the “building repository” on GitHub: https://github.com/MysteriousCode/cfn-lint-docker

The images are pushed to:

Why not use the Dockerfile from `cfn-lint` repo?

The Dockerfile shipped within cfn-lint’s repository installs a specific hard-coded version of cfn-lint from pip. Since both major versions 0.x and 1.x are available, this meant we could not use that file to build the v0.x images.

Additionally, cfn-lint’s Dockerfile does not follow the official docker image consistency guidelines which means it forces a specific entrypoint. This means, that apart from limited use-cases, you’d need to overwrite the entrypoint every time in order to use it.

Examples

To get the image from Docker Hub:

docker pull mysteriouscode/cfn-lint

To get the image from ECR Public:

docker pull public.ecr.aws/mysteriouscode/cfn-lint:latest

Release versions retain with the same tag as the cfn-lint release on Github, for example:

docker pull mysteriouscode/cfn-lint:v0.86.3

Examples in CI

To use within CI, see the following examples:

Jenkins Pipelines

1
2
3
docker.image('mysteriouscode/cfn-lint:latest') {
    sh "cfn-lint --info"
}

GitLab CI

1
2
3
4
5
lint:
  image:
    name: mysteriouscode/cfn-lint:latest
  script:
    - cfn-lint --info

Hopefully, this will make our lives linting CloudFormation templates a little easier.