Building backstage.io TechDocs within the backend Docker image

Posted on Feb 18, 2025

backstage.io has a really interesting feature called TechDocs, which allows you to bundle Markdown documentation alongside your component definitions - Backstage uses mkdocs underneath to generate the documentation pages for displaying in the frontend.

The default configuration for Backstage TechDocs is to generate the docs in a separate Docker container:

techdocs:
  generator:
    runIn: 'docker'

This is fine if you’re running Backstage in a context where you have Docker available, but this isn’t always possible (for example, if you’re running the Backstage container on a managed Kubernetes cluster like AWS EKS and can’t directly pass the Docker socket through to the Backstage container).

In this scenario, you can use the local generator to tell Backstage’s backend to use the local Python installation for mkdocs generation. This requires some extra dependencies and configuration to work properly:

Modify the app-config.yaml

Tell the backend that you want to run the TechDocs generator locally:

techdocs:
  generator:
    runIn: 'local'

Modify the Dockerfile

During the build process, you’ll need to install pip and the relevant mkdocs Python packages. You can do this by adding an extra step to the Dockerfile; this step will need to run before the build user is switched to node, as root access is required to install packages with apt:

# --- other steps beforehand ---

# Install TechDocs dependencies locally
RUN apt update
RUN apt install -y python3-pip
RUN pip3 install --break-system-packages mkdocs mkdocs-techdocs-core

# --- other steps afterwards ---

USER node

In this scenario, it’s OK to pass --break-system-packages to pip, as none of the local Python packages would get overwritten by this operation (and therefore nothing gets broken). Generally speaking, you should avoid passing this argument.

Rebuild the Docker image with these modifications, and run Backstage again - the TechDocs generation should now succeed.

Optional: Conditionally install TechDocs dependencies

It isn’t always desirable to install extra dependencies if you don’t need them (e.g. if TechDocs is disabled, or you’re running Backstage’s container in a context where Docker in Docker is available). You can use a build argument to conditionally run the install steps by modifying your Dockerfile like so:

# Don't install the dependencies by default.
ARG install_techdocs_local=false

# --- other steps beforehand ---

RUN if [[ "$install_techdocs_local" == "true" ]]; then apt update && apt install -y python3-pip && pip3 install --break-system-packages mkdocs mkdocs-techdocs-core; fi

# --- other steps afterwards ---

USER node

With this configuration, the TechDocs dependencies won’t get installed unless you manually specify the build arg when building the Docker image:

# Run this in the root of your Backstage project
docker build ../.. -f Dockerfile --build-arg install_techdocs_local=true --tag backstage