Skip to content

sync

The sync section defines the list of upstream images to mirror.

sync:
hooks:
post_sync:
- cmd: notify-team.sh
timeout: 30s
continue_on_error: true
entries:
- source: docker.io/library/alpine
tag_regex: '^3\.\d+\.\d+$'
keep_last: 3
target: registry.example.com/mirrors/alpine
lifecycle:
product: alpine
track: minor
Field Type Required Default Description
hooks.post_sync []Hook no Commands to run after all sync entries complete
platforms []string no Default platforms to mirror for every entry (override per entry)
Field Type Required Description
source string yes Upstream image reference (e.g. docker.io/library/alpine)
target string yes Destination image reference in your registry
tag string one of tag/tag_regex Sync a single fixed tag
tag_regex string one of tag/tag_regex Sync all tags matching this regex
keep_last integer no Keep only the N most recent matching tags
os_normalize bool no Rename OS-variant tags (e.g. alpine3.211.22-alpine3.21)
check_digest bool no Re-sync even if the tag already exists (digest check)
platforms []string no Restrict the mirrored platforms (overrides sync.platforms)
lifecycle Lifecycle no EOL tracking for this image
hooks Hooks no Per-entry hooks
- source: docker.io/library/alpine
tag: "3.21.3"
target: registry.example.com/mirrors/alpine

Syncs exactly one tag. Useful when you want to pin to a known-good version.

- source: docker.io/library/alpine
tag_regex: '^3\.\d+\.\d+$'
keep_last: 3
target: registry.example.com/mirrors/alpine

imglife queries Docker Hub for all tags matching the regex, sorts them by version (semantic or date fallback), and syncs the keep_last most recent. For Docker Hub images, dates are fetched in a single API call.

Pattern Matches
^3\.\d+\.\d+$ 3.21.3, 3.20.6 — Alpine 3.x
^1\.\d+\.\d+-alpine3\.\d+$ 1.22.3-alpine3.21 — Go on Alpine
^\d+\.\d+$ 22.04, 24.04 — Ubuntu LTS
^\d+\.\d+\.\d+$ Any semver

Several entries may share the same target. Each one is then an independent version line, identified by its tag / tag_regex:

- source: docker.io/library/python
tag_regex: '^3\.12\.\d+-bookworm$'
target: registry.example.com/mirrors/python
keep_last: 2
lifecycle: { product: python, track: minor }
- source: docker.io/library/python
tag_regex: '^3\.13\.\d+-bookworm$'
target: registry.example.com/mirrors/python
keep_last: 1
lifecycle: { product: python, track: minor }

sync, status, cleanup, check, images and eol all resolve tags line by line — the pattern is anchored (^(?:…)$) against the destination tag, after normalisation when os_normalize is set. The displayed tag, the EOL cycle and keep_last never leak from one line to another: cleanup keeps keep_last tags per line, so the 3.13 line no longer evicts the 3.12 one. Tags of a mirror repository matching no line stay ranked together under retention.keep_last.

Regexes are compiled when the config file is loaded — an invalid pattern fails the command instead of silently matching nothing.

The same applies to build.images blocks sharing a folder.

Add lifecycle tracking to connect EOL data to a sync entry:

- source: docker.io/library/alpine
tag_regex: '^3\.\d+\.\d+$'
target: registry.example.com/mirrors/alpine
lifecycle:
product: alpine # product slug on endoflife.date
track: minor # how to derive the cycle from the tag
track value Example tag Resolved cycle
minor 3.21.3 3.21
major 22.04 22

By default imglife skips tags that already exist in the target registry. Enable check_digest: true to re-sync if the upstream digest has changed (e.g. a mutable tag like latest):

- source: docker.io/library/alpine
tag: latest
target: registry.example.com/mirrors/alpine
check_digest: true

By default imglife copies the upstream image as-is, preserving multi-arch manifest lists (OCI image indexes). Set platforms to mirror only a subset. The list resolves per entry: the per-entry platforms overrides the global sync.platforms default; an empty list copies everything.

sync:
platforms:
- linux/amd64 # global default for every entry
entries:
- source: docker.io/library/alpine
tag_regex: '^3\.\d+\.\d+$'
target: registry.example.com/mirrors/alpine
- source: docker.io/library/node
tag: "22-alpine"
target: registry.example.com/mirrors/node
platforms: # per-entry override
- linux/amd64
- linux/arm64

Behaviour by list size:

Platforms Result
empty Full copy — preserves the source manifest list / image as-is
one platform A single-platform image (no index)
several An image index reduced to that subset
sync:
entries:
- source: docker.io/library/alpine
tag_regex: '^3\.\d+\.\d+$'
target: registry.example.com/mirrors/alpine
hooks:
post_sync:
- cmd: curl -s https://hooks.slack.com/... -d '{"text":"alpine synced"}'
timeout: 10s
continue_on_error: true

Hooks are also available at the top level of sync: and run after all entries complete. See Hooks reference for injected environment variables.

Control how many sync entries run concurrently:

Terminal window
export IMGLIFE_SYNC_PARALLELISM=4 # default: 4

For sources that require authentication, provide credentials via environment variables using the normalised hostname:

quay.io/prometheus/prometheus
export IMGLIFE_QUAY_IO_TOKEN=mytoken
# Source: ghcr.io/owner/image
export IMGLIFE_GHCR_IO_USERNAME=myuser
export IMGLIFE_GHCR_IO_PASSWORD=mytoken

See Credentials for the full convention.