Skip to content

Latest commit

 

History

900 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Container Images

License CI Trivy Scan Stars Forks Contributors Issues

Container images built from upstream sources or custom Dockerfiles, published to GitHub Container Registry with automated security scanning and SLSA provenance.

Development

See DEVELOPMENT.md for development environment setup.

Usage

Pull an image:

docker pull ghcr.io/anthony-spruyt/chrony:latest

Adding a New Image

Versions are owned by release-please. See docs/releases.md.

  1. Create a directory named after the image, containing a Dockerfile.

  2. Register the image in release-please-config.json and .release-please-manifest.json.

  3. Add a build job to .github/workflows/release-please.yaml and add the image to the image choice list in .github/workflows/rebuild-release.yaml.

Merging a conventional commit that touches the directory then opens a release PR; merging that cuts the tag and publishes the image.

Variant of an Existing Image

To share another image's sources but use your own Dockerfile, add a metadata.yaml setting build_context:

build_context: llm-guard

Adding a Custom MegaLinter Flavor

Custom MegaLinter flavors extend official flavors with additional linters. The megalinter-factory/ directory contains tooling to generate flavor files from a simple configuration.

Using Claude Code (Recommended)

The /create-megalinter-flavor command automates flavor creation with automatic base flavor selection:

# With specific linters
/create-megalinter-flavor my-ci ACTION_ACTIONLINT,MARKDOWN_MARKDOWNLINT,BASH_SHELLCHECK

# Interactive mode (prompts for linter selection)
/create-megalinter-flavor my-ci

The command will:

  1. Validate the flavor name and check for conflicts
  2. Look up linter configurations from the catalog
  3. Auto-select the optimal base flavor (minimizing custom installs)
  4. Generate megalinter-<name>/flavor.yaml with Renovate annotations

Manual Setup

  1. Create a directory for your flavor:

    mkdir megalinter-<name>/
  2. Create flavor.yaml with your configuration:

    name: my-flavor
    description: "MegaLinter for my use case"
    
    # renovate: datasource=docker depName=oxsecurity/megalinter-ci_light
    upstream_image: "oxsecurity/megalinter-ci_light:v9.3.0@sha256:..."
    
    custom_linters:
      - ACTION_ACTIONLINT
      - MARKDOWN_MARKDOWNLINT
      - PYTHON_BANDIT
  3. Commit flavor.yaml - CI generates Dockerfile and test.sh, then builds automatically

Available Linters

Linter information is extracted directly from MegaLinter's descriptors at build time. The generator automatically fetches the latest versions from https://github.com/oxsecurity/megalinter/tree/main/megalinter/descriptors.

Version Updates

Linter versions are automatically extracted from MegaLinter at build time - no manual tracking needed. The weekly scheduled rebuild workflow picks up any new linter versions.

For the base image, Renovate tracks the upstream MegaLinter version:

# renovate: datasource=docker depName=oxsecurity/megalinter-ci_light
upstream_image: "oxsecurity/megalinter-ci_light:v9.3.0@sha256:..."

When Renovate creates a PR updating flavor.yaml, CI regenerates the Dockerfile and builds.

Local Development

To test locally, generate files first:

pip install pyyaml jinja2
python megalinter-factory/generate.py megalinter-<name>/

Generated files (Dockerfile, test.sh) are regenerated by CI at build time.

Build Triggers

CI builds but never pushes. Every publish goes through release-please — see docs/releases.md.

Automatic

Pushing changes to Dockerfile, flavor.yaml, assets/, metadata.yaml, or .rebuild-stamp builds the affected images. Changes to megalinter-factory/ build all flavors. Publishing happens when the resulting release PR merges.

Manual

Trigger a build with no push via workflow_dispatch:

curl -X POST \
  -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  https://api.github.com/repos/anthony-spruyt/container-images/actions/workflows/ci.yaml/dispatches \
  -d '{"ref":"main","inputs":{"image":"chrony"}}'

To republish a release whose build failed after tagging, use the Rebuild Release workflow instead.

Automatic Version Updates

Renovate updates dependencies inside an image (base images, packages). The resulting commit lands on main and release-please cuts a patch release for that image.

Image versions themselves are never set by Renovate; they live in .release-please-manifest.json.

n8n Workflow (Special Cases)

For upstream sources Renovate cannot monitor, an n8n workflow can watch the source and open an issue. See chrony/n8n-release-watcher.json, which tracks the Alpine chrony package.

Security

See SECURITY.md for security policy and controls.

About

Container images built from upstream sources or custom Dockerfiles, with automated security scanning, release management, and SLSA provenance

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages