Skip to content

End-of-Life Tracking

Using a runtime past its end-of-life date is a security risk: upstream maintainers stop releasing patches for CVEs. In practice, many teams continue using EOL images because there’s no automatic alert.

imglife integrates EOL tracking into the image lifecycle so you’re warned before EOL, not after.

imglife fetches EOL data from endoflife.date, a community-maintained database of release cycles for hundreds of products (Alpine Linux, Go, Node.js, Python, Ubuntu, Debian, etc.).

You can also use a local YAML file as the data source — useful for air-gapped environments or custom runtimes not covered by endoflife.date.

When you run imglife status, each image row includes:

Image EOL date Status
alpine:3.21.3-core1.0.0 2026-11-01 ✅ OK
alpine:3.18.6-core1.0.0 ❌ EOL ❌ Expired
node:20.9.0-core1.0.0 2026-04-30 ⚠️ < 30 days

The alert threshold is configurable:

Terminal window
export IMGLIFE_ALERT_CRITICAL_DAYS=30 # warn when EOL is within 30 days (default)

In your imglife.yaml:

lifecycle:
eol_provider: endoflife # default — fetch from endoflife.date
eol_target: git # store cache file in git (default)
eol_data_file: eol-data.yaml

For air-gapped environments, switch to a local file:

lifecycle:
eol_provider: local
eol_data_file: eol-data.yaml

The eol-data.yaml file format mirrors endoflife.date’s API response:

alpine:
- cycle: "3.21"
eol: "2026-11-01"
latest: "3.21.3"
- cycle: "3.20"
eol: "2026-04-01"
latest: "3.20.6"
golang:
- cycle: "1.22"
eol: "2026-02-01"
latest: "1.22.1"
Terminal window
imglife eol update

This fetches fresh data from endoflife.date for every product that has a lifecycle: entry in your sync.entries — plus the cycles still referenced by applicative build records — and merges the result into eol-data.yaml.

Merging matters: a mirror tag removed by keep_last no longer contributes a cycle, but an application may still run on it. Keeping the known cycles in the cache is what prevents ⚠️ N/A from appearing in the status report. Use imglife eol update --prune to rebuild the file from the collected cycles only.

When a cycle is still missing at read time, imglife falls back on the neighboring cycles: a cycle newer than anything endoflife.date knows inherits the previous cycle’s status if that cycle is still supported, and a cycle older than every known cycle is reported as ⚠️ outdated rather than as unknown.

In CI, run this as a scheduled job (e.g. weekly) to keep the cache current. See Base Images — GitLab CI for an example.

EOL tracking is configured per sync entry:

sync:
entries:
- source: docker.io/library/alpine
tag_regex: '^3\.\d+\.\d+$'
target: registry.example.com/mirrors/alpine
lifecycle:
product: alpine # matches a key in eol-data.yaml / endoflife.date
track: minor # derive cycle from tag: "3.21.3" → "3.21"

The track field tells imglife how to derive the EOL cycle key from the image tag:

Value Example tag Derived cycle
minor 3.21.3 3.21
major 22.04 22

imglife check can also surface EOL data in applicative CI pipelines. When a base image is approaching EOL, the check command:

  • With default flags: warns but succeeds
  • With --strict: fails the job if the base is at or past EOL
Terminal window
# In your app's CI pipeline:
imglife check --base registry.example.com/bases/alpine:3.18.6-core1.0.0 --strict

imglife supports two targets for persisting the EOL cache:

Target Description
git (default) Writes eol-data.yaml to the local filesystem; commit it to git
pkgregistry Uploads the file to the Package Registry (useful when you can’t commit from CI)

Set the target in lifecycle.eol_target in your config.