Skip to content

Docker Build

The builder ships as a Docker image. Content repos run it to produce static HTML without installing Node.js or Astro locally.

docker/Dockerfile uses a multi-step build on node:24-alpine:

FROM node:24-alpine AS builder
WORKDIR /app
# Install deps (cached layer)
COPY package*.json ./
RUN npm ci
# Copy framework code
COPY . .
# Remove placeholder content
RUN rm -rf src/content/docs/*
COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
LayerWhatWhy cached separately
1COPY package*.json + npm ciDependencies change infrequently; caching this layer avoids re-downloading on every build
2COPY . .Framework source code
3rm -rf src/content/docs/*Cleans out any placeholder content so only injected content appears
4COPY entrypoint.shBuild orchestration script

docker/entrypoint.sh runs each time the container starts. It performs these steps in order:

Terminal window
npm install
npm update

Ensures the theme package and all dependencies are at their latest compatible versions.

Terminal window
cp /app/node_modules/@f5xc-salesdemos/docs-theme/astro.config.mjs /app/astro.config.mjs
cp /app/node_modules/@f5xc-salesdemos/docs-theme/src/content.config.ts /app/src/content.config.ts

Copies astro.config.mjs and content.config.ts from the theme package. The theme is the single source of truth for Astro configuration — see Architecture for the theme system design.

Terminal window
if [ -d "$CONTENT_DIR" ]; then
cp -r "$CONTENT_DIR"/* /app/src/content/docs/
else
echo "ERROR: No content found at $CONTENT_DIR"
exit 1
fi

Copies the mounted content into Astro’s content collection directory. Exits with an error if the content directory is missing.

Terminal window
if [ -z "$DOCS_TITLE" ] && [ -f /app/src/content/docs/index.mdx ]; then
DOCS_TITLE=$(grep -m1 '^title:' /app/src/content/docs/index.mdx | sed 's/title: *["]*//;s/["]*$//')
export DOCS_TITLE
fi

If DOCS_TITLE is not set via environment, extracts it from the title: frontmatter field of index.mdx.

Terminal window
if [ -z "$DOCS_BASE" ] && [ -n "$GITHUB_REPOSITORY" ]; then
DOCS_BASE="/${GITHUB_REPOSITORY#*/}"
export DOCS_BASE
fi

Derives the site base path from the GitHub repository name (e.g., owner/my-docs becomes /my-docs).

Terminal window
npm run build

Runs astro build, producing static output in /app/dist/.

Terminal window
if [ -d "$OUTPUT_DIR" ]; then
cp -r /app/dist/* "$OUTPUT_DIR"/
fi

Copies the built site to the output mount point.

VariableDefaultDescription
CONTENT_DIR/content/docsPath to the mounted content directory
OUTPUT_DIR/outputPath where the built site is copied
DOCS_TITLE(extracted from index.mdx)Site title passed to the Astro config
DOCS_DESCRIPTION(extracted from index.mdx)Site description from frontmatter
DOCS_BASE(derived from GITHUB_REPOSITORY)Base path for the site (e.g., /my-docs)
DOCS_SITE(derived from GITHUB_REPOSITORY_OWNER)Site URL passed to the Astro config (e.g., https://<owner>.github.io)
GITHUB_REPOSITORY(set by GitHub Actions)owner/repo string used to derive DOCS_BASE
GENERATE_PDFfalseEnable PDF generation after build
PDF_FILENAMEdocsOutput filename for the generated PDF
LLMS_OPTIONAL_LINKS[]JSON array of child site URLs for the llms.txt Optional section

To build documentation locally using Docker:

Terminal window
docker run --rm \
-v "$(pwd)/docs:/content/docs" \
-v "$(pwd)/output:/output" \
ghcr.io/f5xc-salesdemos/docs-builder:latest

This mounts the local docs/ directory as content and writes the built site to output/.

For content authors who want a live dev server workflow, see Local Preview for Content Authors.

When working on the builder itself (components, plugins, theme integration), you can run Astro’s dev server directly without Docker:

Terminal window
npm ci
cp node_modules/@f5xc-salesdemos/docs-theme/astro.config.mjs astro.config.mjs
cp node_modules/@f5xc-salesdemos/docs-theme/src/content.config.ts src/content.config.ts
# Copy some test content into the content collection
cp -r /path/to/test-content/* src/content/docs/
DOCS_TITLE="Dev Test" npx astro dev --host

Open http://localhost:4321. Hot module replacement (HMR) works for component and plugin changes.

The image is published to GitHub Container Registry:

ghcr.io/f5xc-salesdemos/docs-builder

Two tags are pushed on every build:

TagDescription
latestMost recent build from main
<sha>Full Git commit SHA for reproducible builds

See CI/CD and Governance for the workflow that builds and publishes the image.