Skip to content

docs: adopt Hugo module mount to single-source documentation across github.io and docs.docker.com #3371

Description

@aheritier

Problem

Docker Agent maintains documentation in two places that drift apart:

Because the docs.docker.com pages are hand-authored duplicates, they drift every time the product-repo docs are updated. There is no automated link between the two.

Solution: join the pattern every other Docker product already uses

docker/docs already single-sources product documentation via Hugo module mounts pinned to release tags. Six products are already wired in today:

Product go.mod pin
Docker CLI github.com/docker/cli v29.6.0
Buildx github.com/docker/buildx v0.35.0
Compose github.com/docker/compose/v5 v5.2.0
Model Runner github.com/docker/model-runner v1.1.36
BuildKit github.com/moby/buildkit
Moby API github.com/moby/moby/api

docker-agent is the only outlier. The fix is to join this pattern.

Architecture: one source, two surfaces

docker/docker-agent/docs/   ← SINGLE SOURCE OF TRUTH (written once)
          │
          ├─── builds from HEAD of main ──────────▶  github.io/docker-agent
          │                                           "Edge / preview" docs
          │                                           Tracks main, may show unreleased features
          │                                           Banner links to docs.docker.com
          │
          └─── Hugo module mount, pinned to release ▶  docs.docker.com/manuals/ai/docker-agent
                                                        "Stable / authoritative" docs
                                                        Curated subset, auto-bumped on release
                                                        No page authored twice

How it works:

  • docker/docs go.mod adds github.com/docker/docker-agent vX.Y.Z as a module dependency
  • hugo.yaml module.imports maps docs/**content/manuals/ai/docker-agent
  • On each docker-agent release, a bot PR bumps the version pin — docs.docker.com updates automatically
  • A docs-upstream.yml in this repo calls docker/docs' reusable validate-upstream.yml — docs PRs that would break docs.docker.com fail CI before merging

Open decisions (needed before Phase 1)

  • Subset scope — which of the 85 github.io pages mount onto docs.docker.com? (suggested start: current 17 + getting-started + config reference)
  • github.io renderer — switch to Hugo now (true byte-level single source) or keep Jekyll with portable-Markdown discipline?
  • Canonical direction — confirm docs.docker.com is canonical for mirrored pages
  • Bump trigger — scheduled poll in docker/docs (simpler) vs repository_dispatch from release workflow (tighter)?
  • URL/path stability — confirm canonical product path so mounts and aliases remain stable

Implementation checklist

Phase 0 — Decisions (blocks everything else)

  • Resolve the five open decisions above

Phase 1 — Make the source mountable

  • 1.1 Convert curated doc subset to portable Hugo-clean Markdown: remove Liquid (relative_url), drop permalink: front matter, replace theme-specific HTML grids, add title/description/keywords front matter, use > [!NOTE] callouts
  • 1.2 Add markdownlint + link-check CI on docs/**

Phase 2 — Wire the mount and automation

  • 2.1 Add Hugo module mount in docker/docs: go.mod require entry, hugo.yaml module.imports map, vendor into _vendor/, replace the 17 hand-authored pages with mounted equivalents (preserve aliases so URLs don't break)
  • 2.2 Add docs-upstream.yml in this repo calling docker/docs' reusable validate-upstream.yml
  • 2.3 Add release-bump workflow (bot PR to docker/docs bumping the version pin on each new release tag)

Phase 3 — Stable/preview UX and SEO

  • 3.1 Add preview banner to github.io layout linking to docs.docker.com
  • 3.2 Add rel=canonical on github.io mirrored pages pointing to docs.docker.com equivalents
  • 3.3 Establish availability-badge convention for unreleased features (Coming in vX.Y)

Phase 4 — Converge renderers (recommended fast-follow)

  • 4.1 Switch github.io from Jekyll to Hugo (lightweight config; byte-level single source)
  • 4.2 Expand mounted subset toward full coverage; retire remaining stubs

Minimum viable outcome

Phases 1–2 eliminate duplication and stop drift with no ongoing manual work. Phases 3–4 improve UX/SEO and achieve true byte-level single source.

References

  • docker/docs go.mod — declares upstream module dependencies
  • docker/docs sync-cli-docs.yml — model for the release-bump workflow
  • docker/docs validate-upstream.yml — reusable upstream validation workflow
  • Buildx docs-upstream.yml / Compose docs-upstream.yml — model for the product-side CI hook

Metadata

Metadata

Labels

area/docsDocumentation changes

Type

Fields

No fields configured for Epic.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions