Files
docker-docs/Dockerfile
T
David Karlsson 9b1f7de05f docs: unify Hub, DVP, and Registry API references (#26048)
@netlify /reference/api/

[Preview the API
reference](https://deploy-preview-26048--docsdocker.netlify.app/reference/api/)

Adds a shared API reference experience for Hub, DVP, and Registry: a
catalog, operation navigation, linked schemas, request and response
examples, and matching HTML and Markdown output. A validation and
generation pipeline prepares the reference data for Hugo and runs as
part of Docker and Netlify builds.

Migrates the three specifications to OpenAPI 3.2, correcting response
shapes, nullable fields, and authentication and token examples. The Hub
migration also corrects SCIM contracts and CSV exports; DVP gains
complete report response schemas and examples. Registry keeps its
documented Hub-specific subset, with authentication and media
negotiation expressed through OpenAPI security and content fields.

Validation is strict for both checks and generation, with no exception
baseline or bypass flag. The build uses the migrated sources directly,
without migration scripts or records.

Page and specification URLs remain stable, including the DVP alias.
Operation and schema anchors change. Engine and Governance retain their
existing references.

Validated locally with Go tests, strict validation of all three
specifications (zero diagnostics), scoped formatting and lint, and a
full Hugo build checking all 176 HTML/Markdown page pairs, example
parity, reference links, and byte-identical published specifications. A
browser check confirmed raw CSV rendering and the generated request
header. No live API requests were made.
2026-09-17 16:56:32 +02:00

182 lines
5.4 KiB
Docker

# syntax=docker/dockerfile:1
# check=skip=InvalidBaseImagePlatform
ARG ALPINE_VERSION=3.23
ARG GO_VERSION=1.26
ARG HTMLTEST_VERSION=0.17.0
ARG VALE_VERSION=3.17.0
ARG HUGO_VERSION=0.163.0
ARG NODE_VERSION=24
ARG PAGEFIND_VERSION=1.5.2
# base defines the generic base stage
FROM golang:${GO_VERSION}-alpine${ALPINE_VERSION} AS base
RUN apk add --no-cache \
bash \
git \
nodejs \
npm \
gcompat \
rsync
# npm downloads Node.js dependencies
FROM base AS npm
ENV NODE_ENV="production"
WORKDIR /out
RUN --mount=source=package.json,target=package.json \
--mount=source=package-lock.json,target=package-lock.json \
--mount=type=cache,target=/root/.npm \
npm ci
# hugo downloads the Hugo binary
FROM base AS hugo
ARG TARGETARCH
ARG HUGO_VERSION
WORKDIR /out
ADD https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-${TARGETARCH}.tar.gz .
RUN tar xvf hugo_extended_${HUGO_VERSION}_linux-${TARGETARCH}.tar.gz
# build-base is the base stage used for building the site
FROM base AS build-base
WORKDIR /project
COPY --from=hugo /out/hugo /bin/hugo
COPY --from=npm /out/node_modules node_modules
COPY . .
RUN --mount=type=cache,target=/root/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
./hack/api-docs/run.sh test && ./hack/api-docs/run.sh generate
# build creates production builds with Hugo
FROM build-base AS build
# HUGO_ENV sets the hugo.Environment (production, development, preview)
ARG HUGO_ENV="development"
# DOCS_URL sets the base URL for the site
ARG DOCS_URL="https://docs.docker.com"
ENV HUGO_CACHEDIR="/tmp/hugo_cache"
RUN --mount=type=cache,target=/tmp/hugo_cache \
hugo \
--gc \
--minify \
--panicOnWarning \
--printPathWarnings \
--printUnusedTemplates \
-b $DOCS_URL \
-e $HUGO_ENV
RUN node --test hack/test/flatten-and-resolve.mjs
RUN node hack/flatten-and-resolve.js public
RUN node hack/api-docs/verify-output.mjs public
# lint lints markdown files
FROM ghcr.io/rvben/rumdl:0.2.49-alpine AS lint
RUN --mount=type=bind,target=. rumdl check content
# test validates HTML output and checks for broken links
FROM wjdp/htmltest:v${HTMLTEST_VERSION} AS test
WORKDIR /test
COPY --from=build /project/public ./public
ADD .htmltest.yml .htmltest.yml
RUN htmltest
# vale
FROM jdkato/vale:v${VALE_VERSION} AS vale-run
WORKDIR /src
ARG GITHUB_ACTIONS
RUN --mount=type=bind,target=.,rw <<EOT
set -e
mkdir /out
args=""
[ "$GITHUB_ACTIONS" = "true" ] && args="--output=.vale-rdjsonl.tmpl"
set -x
vale sync
vale $args content/ | tee /out/vale.out
EOT
FROM scratch AS vale
COPY --from=vale-run /out/vale.out /
# update-modules downloads and vendors Hugo modules
FROM build-base AS update-modules
# MODULE is the Go module path and version of the module to update
ARG MODULE
RUN <<"EOT"
set -ex
if [ -n "$MODULE" ]; then
hugo mod get ${MODULE}
else
echo "no module set";
fi
EOT
RUN hugo mod vendor
# vendor is an empty stage with only vendored Hugo modules
FROM scratch AS vendor
COPY --from=update-modules /project/_vendor /_vendor
COPY --from=update-modules /project/go.* /
FROM base AS validate-vendor
RUN --mount=target=/context \
--mount=type=bind,from=vendor,target=/out \
--mount=target=.,type=tmpfs <<EOT
set -e
rsync -a /context/. .
git add -A
rm -rf _vendor
cp -rf /out/* .
if [ -n "$(git status --porcelain -- go.mod go.sum _vendor)" ]; then
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "make vendor"'
git status --porcelain -- go.mod go.sum _vendor
exit 1
fi
EOT
# build-upstream builds an upstream project with a replacement module
FROM build-base AS build-upstream
# UPSTREAM_MODULE_NAME is the canonical upstream repository name and namespace (e.g. moby/buildkit)
ARG UPSTREAM_MODULE_NAME
# UPSTREAM_REPO is the repository of the project to validate (e.g. dvdksn/buildkit)
ARG UPSTREAM_REPO
# UPSTREAM_COMMIT is the commit hash of the upstream project to validate
ARG UPSTREAM_COMMIT
# HUGO_MODULE_REPLACEMENTS is the replacement module for the upstream project
ENV HUGO_MODULE_REPLACEMENTS="github.com/${UPSTREAM_MODULE_NAME} -> github.com/${UPSTREAM_REPO} ${UPSTREAM_COMMIT}"
RUN hugo --ignoreVendorPaths "github.com/${UPSTREAM_MODULE_NAME}"
# validate-upstream validates HTML output for upstream builds
FROM wjdp/htmltest:v${HTMLTEST_VERSION} AS validate-upstream
WORKDIR /test
COPY --from=build-upstream /project/public ./public
ADD .htmltest.yml .htmltest.yml
RUN htmltest
# unused-media checks for unused graphics and other media
FROM alpine:${ALPINE_VERSION} AS unused-media
RUN apk add --no-cache fd ripgrep
WORKDIR /test
RUN --mount=type=bind,target=. ./hack/test/unused_media
# pagefind installs the Pagefind runtime
FROM base AS pagefind
ARG PAGEFIND_VERSION
COPY --from=build /project/public ./public
RUN --mount=type=bind,src=pagefind.yml,target=pagefind.yml \
npx pagefind@v${PAGEFIND_VERSION} --output-path "/pagefind"
# index generates a Pagefind index
FROM scratch AS index
COPY --from=pagefind /pagefind .
# test-go-redirects checks that the /go/ redirects are valid
FROM alpine:${ALPINE_VERSION} AS test-go-redirects
WORKDIR /work
RUN apk add yq
COPY --from=build /project/public ./public
RUN --mount=type=bind,target=. <<"EOT"
set -ex
./hack/test/go_redirects
EOT
# release is an empty scratch image with only compiled assets
FROM scratch AS release
COPY --from=build /project/public /
COPY --from=pagefind /pagefind /pagefind