Skip to content

Plugin: publisher-docker

@semrel/publisher-docker tags and pushes one image that already exists in a Docker-compatible daemon. The canonical typed name is required: @semrel/updater-docker retains the historical untyped Docker aliases.

After the first plugin release is available:

Terminal window
semrel plugin install @semrel/publisher-docker

semrel plugin install downloads the binary to .semrel/plugins/ and updates .semrel.lock. Commit .semrel.lock to pin the version for your team.

Run semrel and the plugin on the host that owns the built image. The plugin requires:

  • a docker CLI on PATH;
  • a reachable Docker-compatible daemon that contains the source image;
  • registry authentication configured before execution, for example through docker login or a CI credential helper.

The plugin does not accept credentials or perform login. If semrel runs in a container, provide the Docker CLI, explicitly mount the daemon socket, and mount the appropriate Docker authentication configuration. Access to the Docker daemon socket is effectively root-equivalent access to the host. Only provide it to trusted jobs and containers.

Build and authenticate before running semrel:

Terminal window
docker build --tag acme-api:build .
printf '%s' "$GHCR_TOKEN" |
docker login ghcr.io --username "$GHCR_USER" --password-stdin
semrel release

Configure the release phase:

version: 1
plugins:
- uses: @semrel/publisher-docker
phase: release
args:
image: acme-api:build
ref: ghcr.io/acme/api:{version}

References with registry ports are supported:

ref: registry.example:5000/team/api:{version}

Semrel maps args.image and args.ref to the plugin subprocess environment.

Configuration / variableRequiredDefaultDescription
image / SEMREL_PLUGIN_IMAGEyesExisting local image reference or image ID.
ref / SEMREL_PLUGIN_REFyesTagged destination reference containing {version}. Digest destinations are rejected.
SEMREL_VERSIONone version variableRelease version. Takes precedence over SEMREL_NEXT_VERSION.
SEMREL_NEXT_VERSIONfallbackUsed only when SEMREL_VERSION is empty.
SEMREL_DRY_RUNnofalsetrue or 1 inspects and plans without tagging or pushing.

One leading v is removed from the release version. SemVer build metadata uses +, which is not valid in a Docker tag, so + is encoded as _. For example, v1.4.0+build.7 resolves to the tag 1.4.0_build.7.

Empty values, CR/LF or other control characters, unresolved placeholders, digest destinations, untagged destinations, and invalid Docker references are rejected before mutation.

For each invocation, the plugin:

  1. inspects the source image;
  2. inspects the destination and decides whether its tag must be created, replaced, or kept;
  3. tags only when necessary;
  4. inspects the destination again and verifies that it identifies the source;
  5. executes exactly one docker image push;
  6. reports a trustworthy immutable repository@sha256:... reference parsed from the push or the matching RepoDigests entry.

Example output:

publisher-docker: published ghcr.io/acme/api:1.4.0 as ghcr.io/acme/api@sha256:...

Docker command diagnostics are sanitized rather than copied verbatim, so daemon or registry errors do not disclose credentials.

Direct plugin dry-run still requires the Docker CLI, daemon, and source image. It inspects the source and destination and prints whether it would create, replace, or keep the tag. It never tags and never pushes, so it creates neither a local destination tag nor a remote manifest.

Terminal window
SEMREL_PLUGIN_IMAGE=acme-api:build \
SEMREL_PLUGIN_REF='ghcr.io/acme/api:{version}' \
SEMREL_VERSION=v1.4.0 \
SEMREL_DRY_RUN=true \
semrel-plugin-publisher-docker

The MVP does not build images, log in, sign, retry, apply tag policies, create channel tags, or assemble multi-platform images/manifests.