Skip to content

How To Use Mkdocs + Meterial In Kubernetes

Preface

In this guide I show you how I use mkdocs in my Kubernetes cluster.
There are uncountable ways to do something similar, but I think this post can be useful for you.
The main ascpect of my solution is to build the documentation in an init container, and serve the page with nginx. This way the only thing you have to do is rollout the deployment after new version of your mkdocs is released (pushed to your repository).

Required Containers

Git Downloader

This container aims to download the git repository to the ephemeral storage. If you don't want to use my repository you can build your own image.

Dockerfile

quay.io/jvincze84/mkdocs-init:v0.7
FROM alpine:latest
RUN apk add \
bash \
git
ADD run.sh /
CMD ["/run.sh"]

As you can see It's a really simple Dockerfile based on the latest alpine image.

Shell Scirpt

run.sh
#!/bin/bash
GIT_URL="${GIT_URL:-gogs.vincze.work}"
GIT_REPO="${GIT_REPO:-jvincze/priv-knowledge-mkdocs}"
GIT_USER="${GIT_USER:-jvincze}"
GIT_PASS="${GIT_PASS:-admin}"
GIT_AUTH="${GIT_AUTH:-true}"
USER_UID="${USER_UID:-1000}"

STORAGE="${STORAGE:-/storage}"

echo "=== DEBUG & Avaiable Variables==="
echo "GIT_URL: $GIT_URL"
echo "GIT_REPO: $GIT_REPO"
echo "GIT_USER: $GIT_USER"
echo "GIT_AUTH: $GIT_AUTH"
echo "GIT_PASS: ********"
echo "USER_UID: $USER_UID"

[ ! -d $STORAGE ] && mkdir -p $STORAGE


cd $STORAGE

if [ $GIT_AUTH == "true" ]
then
  git clone https://$GIT_USER:$GIT_PASS@$GIT_URL/$GIT_REPO .
else
  git clone https://$GIT_URL/$GIT_REPO .
fi


echo
echo "--- Setting permissions"
chown -R $USER_UID:$USER_UID $STORAGE

ls -la $STORAGE
echo "Container Done"

Warning

You should not modify the $STORAGE environment variable unless you change the Deployment as well.

Important

When you create the run.sh file, don't forget to add the executable bit. (chmod +x run.sh)

Mkdocs Builder

This container will build the site for the nginx web server.

Dockerfile

quay.io/jvincze84/mkdocs-build:2.14
FROM python:3-alpine3.14


ARG USER=1000

RUN adduser -h /usr/src/mkdocs -D -u $USER mkdocs \
&& apk add bash \
&& apk add git 

ENV PATH="${PATH}:/usr/src/mkdocs/.local/bin"

USER mkdocs
RUN mkdir -p /usr/src/mkdocs/build
WORKDIR /usr/src/mkdocs/build

RUN pip install --upgrade pip

RUN pip install pymdown-extensions \
&& pip install mkdocs \
&& pip install mkdocs-material \
&& pip install mkdocs-rtd-dropdown \
&& pip install mkdocs-git-revision-date-plugin \
&& pip install mkdocs-git-revision-date-localized-plugin \
&& pip install mkdocs-blog-plugin \
&& pip3 install mkdocs-blogging-plugin

# The following line is bcause of mkdocs build error: Unable to read git logs of
RUN git config --global --add safe.directory '*'

ENTRYPOINT ["/usr/src/mkdocs/.local/bin/mkdocs"]

LABEL mkdocs.image="3-alpine3.14"

Warning

The USER argument must match with the USER_UID in the previous step. (Git Downloader / Shell Scirpt)

You can add extra extension(s) by modifying the pip install section, any other parts of the Dockerfile should not be modified.

Deployment

Let's see the Depolyment yaml file.

kind: Deployment
apiVersion: apps/v1
metadata:
  name: read-the-docs
  namespace: mkdocs
spec:
  replicas: 1
  selector:
    matchLabels:
      k8s-app: mkdocs-priv
  template:
    metadata:
      name: mkdocs-priv
      creationTimestamp: null
      labels:
        k8s-app: mkdocs-priv
    spec:
      volumes:
        - name: shared
          emptyDir: {}
      initContainers:
        - name: git
          image: quay.io/jvincze84/mkdocs-init:v0.7
          env:
            - name: GIT_AUTH
              value: 'false'  
            - name: GIT_REPO
              value: jvincze84/jvincze84.github.io
            - name: GIT_URL
              value: github.com
          resources: {}
          volumeMounts:
            - name: shared
              mountPath: /storage
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
        - name: build
          image: quay.io/jvincze84/mkdocs-build:2.14
          args:
            - build
            - '--clean'
            - '--site-dir'
            - /usr/src/mkdocs/build/srv
          resources: {}
          volumeMounts:
            - name: shared
              mountPath: /usr/src/mkdocs/build
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: IfNotPresent
      containers:
        - name: nginx
          image: nginx:latest
          resources: {}
          volumeMounts:
            - name: shared
              mountPath: /usr/share/nginx/html
              subPath: srv
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
          imagePullPolicy: Always
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
      dnsPolicy: ClusterFirst
      securityContext: {}
      schedulerName: default-scheduler
  strategy:
    type: Recreate
  revisionHistoryLimit: 10
  progressDeadlineSeconds: 600

The following environment variabels in the git initContainer must be set accoring to your Git repository:

  • GIT_AUTH: true or false. If your git repository uses auth set to true otherwise false.
  • GIT_URL: URL of your repository. (Example: github.com) Only https is supported. If you need plain http connection you have to modify the run.sh shell script (git clone).
  • GIT_REPO: You can copy paste this value from the git URL in your browser. Example: https://github.com/jvincze84/jvincze84.github.io --> jvincze84/jvincze84.github.io
  • GIT_USER: Your git username. Mandatory if you set GIT_AUTH to true.
  • GIT_PASS: Your git password or token. Mandatory if you set GIT_AUTH to true.

Additionally you may want to use kuberntes secret for storing the git password. In this case you have to add the following lines to the Deployment:

          env:
            - name: GIT_PASS
              valueFrom:
                secretKeyRef:
                  name: gitpass
                  key: gitpass

You can create the secret with the following command:

kubectl -n mkdocs create secret generic gitpass --from-literal=gitpass=1234

Info

  • The Deployment uses ephemeral storage (emptyDir: {}) so every time you deploy a new version or rollout the deployment the entire webpage is regenerated and the previous version won't be kept
  • volumeMounts, mountPath and subPath should not be modified, unless you know what, how and why you do that.

Tip

After you have done with the modification on your docs and pushed back to git, you can rollout the deployment with this command: kubectl rollout restart -n mkdocs deployment read-the-docs. Or simply delete the pod. :)


Last update: October 20, 2022