ADR Guard container image
ADR Guard is published as a multi-platform OCI container image in two registries:
- GitHub Container Registry (GHCR):
ghcr.io/rodri-oliveira-dev/adr-guard - Docker Hub:
docker.io/rodrigodotnet/adr-guard
Both registries receive the same release build for linux/amd64 and linux/arm64.
Stable releases publish four tag levels:
1.2.31.21latestFor reproducible automation, prefer the exact SemVer tag or, when strict immutability is required, pin the image by digest.
Pull the image
Section titled “Pull the image”GHCR:
docker pull ghcr.io/rodri-oliveira-dev/adr-guard:latestDocker Hub:
docker pull rodrigodotnet/adr-guard:latestValidate ADRs
Section titled “Validate ADRs”Mount the repository at /workspace, which is the image working directory:
docker run --rm \ -v "$PWD:/workspace:ro" \ ghcr.io/rodri-oliveira-dev/adr-guard:latest \ check docs/adrValidation can use a read-only mount because check does not write repository files.
The reusable GitHub Action applies stricter defaults on top of this image: read-only root filesystem, read-only consumer workspace for check, all Linux capabilities dropped, no-new-privileges, and networking disabled. See the GitHub Action security model.
Generate the ADR index
Section titled “Generate the ADR index”index writes to the mounted repository. On Linux and macOS, using the host UID/GID avoids ownership mismatches on generated files:
docker run --rm \ --user "$(id -u):$(id -g)" \ -v "$PWD:/workspace" \ ghcr.io/rodri-oliveira-dev/adr-guard:latest \ index docs/adrThe image itself defaults to a non-root user. The explicit --user option above is only for matching ownership on writable host mounts where required.
Offline new and custom templates (available from v1.1.0)
Section titled “Offline new and custom templates (available from v1.1.0)”Published container images include new and custom-template support starting with v1.1.0. Use a published stable image; no feature-branch build is required. For moving-major consumption use :1, or pin an exact SemVer tag/digest when reproducibility is required:
mkdir -p docs/adrdocker run --rm --user "$(id -u):$(id -g)" \ -v "$PWD:/workspace" ghcr.io/rodri-oliveira-dev/adr-guard:1 \ new docs/adr --title "Adopt Redis" --template minimal --culture en-US
docker run --rm --user "$(id -u):$(id -g)" \ -v "$PWD:/workspace" ghcr.io/rodri-oliveira-dev/adr-guard:1 \ new docs/adr --title "Adopt Cache" \ --template-file docs/examples/templates/team.en-US.md
docker run --rm -v "$PWD:/workspace:ro" \ ghcr.io/rodri-oliveira-dev/adr-guard:1 check docs/adrdocker run --rm --user "$(id -u):$(id -g)" \ -v "$PWD:/workspace" ghcr.io/rodri-oliveira-dev/adr-guard:1 \ index docs/adrnew is offline and secret-free: do not provide OPENAI_API_KEY or other provider credentials. The directory must already exist and be writable by the container user; the template file resolves relative to the container’s /workspace working directory and must be readable. Use a read-only mount for new --preview/--dry-run, which print the proposed Markdown without writing. A real new does not update the index automatically. Earlier v1.0.x images do not include these options.
See offline creation, validated examples and exit codes, custom placeholders and template-based AI draft/privacy. The published GitHub Action @v1 supports check, index, and opt-in review; new and AI-assisted draft remain CLI/direct-container workflows.
AI-assisted drafting
Section titled “AI-assisted drafting”Provider credentials must be supplied at runtime through environment variables. They are never baked into the image.
Example with OpenAI:
docker run --rm \ --user "$(id -u):$(id -g)" \ -e OPENAI_API_KEY \ -v "$PWD:/workspace" \ ghcr.io/rodri-oliveira-dev/adr-guard:latest \ draft docs/adr \ --title "Adopt a message broker" \ --context "We need asynchronous integration." \ --provider openai \ --model <openai-model>The same environment-variable rules documented for the .NET Tool apply to Anthropic, Gemini, and OpenAI-compatible providers.
Supply-chain controls
Section titled “Supply-chain controls”The container path is protected by multiple independent controls:
- Hadolint is a required CI gate for the
Dockerfile; - Dependabot monitors the .NET base images referenced by the
Dockerfile; - CI builds and smoke-tests the image before a release can run;
- Trivy scans the built CI image for fixable
HIGHandCRITICALOS/library vulnerabilities and fails the workflow when any are found; - the runtime image is based on the .NET chiseled image and runs as a non-root user;
- release images carry OCI source, documentation, author, license, version, and revision metadata;
- BuildKit publishes an SBOM attestation and
mode=maxprovenance attestation with each multi-platform release; - the release workflow verifies that both
linux/amd64andlinux/arm64manifests and attestation manifests are present in GHCR and Docker Hub.
The SBOM and provenance are OCI attestations associated with the published image index rather than files embedded inside the runtime filesystem.
Inspect a release
Section titled “Inspect a release”Inspect the multi-platform manifest and associated attestations:
docker buildx imagetools inspect \ ghcr.io/rodri-oliveira-dev/adr-guard:1.2.3To use an immutable image reference, resolve the digest and pin it:
ghcr.io/rodri-oliveira-dev/adr-guard@sha256:<digest>Release flow
Section titled “Release flow”Container images are published only after the CI workflow for the validated main commit succeeds. The release workflow then resolves the same SemVer version used by the NuGet package, creates/verifies the Git tag, publishes the multi-platform image to GHCR and Docker Hub, verifies the published manifests and attestations, and only then completes the GitHub Release.