MkDocs com Docker e Live Reload automático
Documentação do setup de um servidor MkDocs rodando em Docker com atualização automática ao editar documentos via FileBrowser, sem necessidade de reiniciar o container ou acessar via SSH.
Visão geral
A solução utiliza uma imagem Docker customizada baseada no squidfunk/mkdocs-material, com um script de entrypoint que faz polling a cada 5 segundos nos arquivos .md e .yml. Quando uma mudança é detectada, o processo do MkDocs é reiniciado automaticamente.
Estrutura de diretórios
/home/ubuntu/
├── mkdocs/ # Conteúdo da documentação
│ ├── docs/
│ │ ├── Automação/
│ │ ├── Fiocruz/
│ │ ├── Inteligência Artificial/
│ │ ├── Linux Desktop/
│ │ ├── Teste/
│ │ ├── assets/
│ │ │ ├── styles/
│ │ │ │ └── custom.css
│ │ │ └── javascripts/
│ │ │ └── custom.js
│ │ └── index.md
│ └── mkdocs.yml
│
└── mkdocs-build/ # Arquivos para build da imagem
├── Dockerfile
└── entrypoint.sh
Pré-requisitos
- Docker instalado no servidor
- FileBrowser ou acesso ao sistema de arquivos para editar os documentos
- Porta
8005disponível no servidor
Passo 1 — Criar a estrutura de diretórios
mkdir -p /home/ubuntu/mkdocs/docs/assets/styles
mkdir -p /home/ubuntu/mkdocs/docs/assets/javascripts
mkdir -p /home/ubuntu/mkdocs-build
Passo 2 — Criar o arquivo mkdocs.yml
Crie o arquivo /home/ubuntu/mkdocs/mkdocs.yml com o seguinte conteúdo:
site_name: Docs@RuiOgawa
theme:
name: material
features:
- navigation.top
- navigation.path
- navigation.indexes
- navigation.instant
- content.code.copy
- content.tabs.link
- search.suggest
- search.highlight
palette:
- scheme: default
primary: indigo
accent: indigo
toggle:
icon: material/weather-night
name: Switch to dark mode
- scheme: slate
primary: indigo
accent: indigo
toggle:
icon: material/weather-sunny
name: Switch to light mode
plugins:
- awesome-pages
extra_css:
- assets/styles/custom.css
extra_javascript:
- assets/javascripts/custom.js
Passo 3 — Criar o Dockerfile
Crie o arquivo /home/ubuntu/mkdocs-build/Dockerfile:
FROM squidfunk/mkdocs-material:latest
RUN pip install --no-cache-dir \
mkdocs-awesome-pages-plugin \
watchdog
WORKDIR /docs
EXPOSE 8000
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/sbin/tini", "--", "/entrypoint.sh"]
O que cada instrução faz
FROM squidfunk/mkdocs-material:latest— usa a imagem oficial do MkDocs Material como basepip install— instala o pluginawesome-pages(navegação automática) ewatchdog(monitoramento de arquivos)WORKDIR /docs— define o diretório de trabalho como/docs, onde o volume será montadoCOPY entrypoint.sh— copia o script de controle para dentro da imagemENTRYPOINT— usa otinicomo init process e executa o entrypoint customizado
Passo 4 — Criar o entrypoint.sh
Crie o arquivo /home/ubuntu/mkdocs-build/entrypoint.sh:
#!/bin/sh
DOCS_DIR="/docs"
get_hash() {
find "$DOCS_DIR" -type f \( -name "*.md" -o -name "*.yml" \) -print0 | \
sort -z | \
xargs -0 md5sum 2>/dev/null | md5sum
}
mkdocs serve --dev-addr=0.0.0.0:8000 &
MKDOCS_PID=$!
echo "MkDocs iniciado com PID $MKDOCS_PID"
LAST_HASH=$(get_hash)
while true; do
sleep 5
CURRENT_HASH=$(get_hash)
if [ "$CURRENT_HASH" != "$LAST_HASH" ]; then
echo "Mudança detectada! Reiniciando MkDocs..."
kill $MKDOCS_PID 2>/dev/null
wait $MKDOCS_PID 2>/dev/null
sleep 1
mkdocs serve --dev-addr=0.0.0.0:8000 &
MKDOCS_PID=$!
LAST_HASH=$(get_hash)
echo "MkDocs reiniciado com PID $MKDOCS_PID"
fi
done
Como o script funciona
- Define
/docscomo diretório monitorado - A função
get_hashpercorre todos os arquivos.mde.ymlrecursivamente, gera um MD5 de cada um e combina tudo num hash único — usando-print0exargs -0para lidar corretamente com nomes de arquivos com espaços e caracteres especiais - Inicia o
mkdocs serveem background e guarda o PID - Entra em loop infinito verificando a cada 5 segundos se o hash mudou
- Se mudou: mata o processo anterior, aguarda encerramento, reinicia o MkDocs e atualiza o hash
Por que polling e não inotify?
O inotify (mecanismo padrão do Linux para watch de arquivos) não propaga eventos corretamente para dentro de containers Docker em bind mounts. O polling viamd5sumé a solução mais compatível e confiável nesse cenário.
Passo 5 — Build da imagem
cd /home/ubuntu/mkdocs-build
docker build -t mkdocs-rui:latest .
A imagem será criada localmente com o nome mkdocs-rui:latest.
Passo 6 — Criar o docker-compose.yml
Crie o arquivo /home/ubuntu/mkdocs/docker-compose.yml:
version: '3.8'
services:
mkdocs:
image: mkdocs-rui:latest
pull_policy: never
container_name: mkdocs_documentation
ports:
- "8005:8000"
volumes:
- /home/ubuntu/mkdocs:/docs
restart: unless-stopped
pull_policy: neveré necessário porque a imagemmkdocs-ruié local e não está em nenhum registry público. Sem essa diretiva, o Docker tentará baixá-la e falhará.
Passo 7 — Subir o container
cd /home/ubuntu/mkdocs
docker compose up -d
Para recriar o container após um novo build da imagem:
docker compose up -d --force-recreate mkdocs
Verificando o funcionamento
Verificar se o container está rodando
docker ps | grep mkdocs
Acompanhar os logs em tempo real
docker logs -f mkdocs_documentation
Saída esperada ao iniciar:
MkDocs iniciado com PID 8
INFO - Building documentation...
INFO - Documentation built in 0.58 seconds
INFO - [23:06:23] Serving on http://0.0.0.0:8000/
Saída esperada ao editar um arquivo:
Mudança detectada! Reiniciando MkDocs...
MkDocs reiniciado com PID 94
INFO - Building documentation...
INFO - Documentation built in 0.60 seconds
INFO - [23:07:18] Serving on http://0.0.0.0:8000/
Acessar a documentação
http://<ip-do-servidor>:8005
Fluxo de atualização
Editar .md no FileBrowser
↓
Salvar o arquivo
↓
Script detecta mudança (em até 5 segundos)
↓
MkDocs reinicia automaticamente
↓
Documentação atualizada no browser
Rebuild da imagem (quando necessário)
Se precisar atualizar o Dockerfile ou o entrypoint.sh:
# 1. Editar os arquivos em /home/ubuntu/mkdocs-build/
# 2. Rebuildar a imagem
cd /home/ubuntu/mkdocs-build
docker build -t mkdocs-rui:latest .
# 3. Recriar o container
cd /home/ubuntu/mkdocs
docker compose up -d --force-recreate mkdocs