World map

 

BM: Baca dalam Bahasa Melayu

World C2: Container Pipelines

Lint with hadolint and actionlint

You will learn: to let robots proofread your recipe and your workflows.

Checked with GitHub Actions 2026-10 on 31 Oct 2026

The problem

bash
hadolint Dockerfile
Dockerfile:1 DL3007 warning: Using latest is prone to errors if the image will ever update. Pin the version explicitly to a release tag
hadolint checks the Dockerfile and warns about DL3007: using latest.

Last month node:latest jumped a version, and the shop broke overnight. A linter: A proofreader robot. It finds mistakes and risky habits in a file before it runs. would have warned you. Plain words: pin a version, like node:24-alpine.

Predict

Your Dockerfile still says FROM node:latest. Tap the station that will stop the line, then press Run.

Which station will stop the line? Tap it, then press Run.

What happened on GitHub

Workflow file .github/workflows/lint.yml

name: Lint
on:
pull_request:
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: hadolint/hadolint-action@v3.1.0
with:
dockerfile: Dockerfile
- name: Lint workflows
run: docker run --rm -v "$PWD:/repo" -w /repo rhysd/actionlint:1.7.12

The line

Pull request · feature → main

Watch

bash
docker run --rm -v "$PWD:/repo" -w /repo rhysd/actionlint:1.7.12 .github/workflows/image.yml
.github/workflows/image.yml:14:3: job "scan" needs job "imgae" which does not exist in this workflow [job-needs]
|
14 | scan:
| ^~~~~
actionlint reads image.yml and finds that job scan needs a job called imgae, which does not exist.

actionlint proofreads workflow files. It caught a typo before GitHub did: imgae. The official image runs it with no install.

Try it

Which robot catches which mistake?

Drag a card into a box. Or tap the card, then tap the box.

      Check

      Where should the lint job sit on the belt?

      Pick one answer.

      You did it!

      You can now let hadolint and actionlint proofread every PR.

      Go deeper (optional)

      hadolint also checks the shell in RUN lines, with ShellCheck. To skip one rule, put # hadolint ignore=DL3007 above that line. Only do it with a good reason. actionlint checks run: scripts too, when ShellCheck is installed.

      Real rep (optional), on your own machine with Docker:

      Real mission

      1. docker run --rm -i hadolint/hadolint:v2.14.0 < Dockerfile
      2. docker run --rm -v "$PWD:/repo" -w /repo rhysd/actionlint:1.7.12

      0 of 3 steps done · Your ticks are saved.