Linux上用MkDocs部署静态文档网站:Nginx外部访问实践
前阵子团队准备把散落在各个地方的项目文档归拢起来腾讯文档、语雀、GitHub Wiki 里各有一份版本对不上新人来了根本不知道该信哪个。我当时的想法很简单文档要统一、要能像网站一样浏览、最好还能交给后端同事直接用 Markdown 维护。最后选中的方案是 MkDocs——一个基于 Python 的静态文档网站生成器在 Linux 服务器上部署将文档内容以 Markdown 文件格式存放一键构建成 HTML 网站再通过 Nginx 实现外部访问整个流程跑通后我忍不住感慨这大概是我见过最省心的文档方案。如果你也在 Linux 上折腾文档站这篇文章完整记录了我从安装、配置到外部访问的全过程照着做就能跑通。1. 为什么是 MkDocs文档网站的选型思路1.1 痛点场景文档散落带来的协作成本做过团队项目的人应该都有体会文档一旦多了管理就成了灾难。需求文档在语雀、接口文档在 ShowDoc、部署手册塞在 Git 仓库的 README 里还有一部分在微信聊天记录里躺尸。新人入职第一个星期基本都在问这个文档在哪这个版本是不是最新的。这种碎片化状态带来的协作损耗比代码本身复杂的问题更隐蔽却又真实影响效率。我当时的核心诉求有三个第一文档必须统一存放、统一入口任何人打开同一个 URL 就能看到最新版本第二维护成本要低团队里不是每个人都会写 HTML但基本都会 Markdown第三上线要快我不希望为了一个文档站去单独买数据库、装 CMS、配 PHP 环境那属于杀鸡用牛刀。MkDocs 恰好完美命中这三点。它做的事情本质上是把 Markdown 翻译成静态 HTML 网站不需要数据库不需要动态语言运行时构建产物就是一堆纯静态文件扔到任意 Web 服务器上就能跑。1.2 MkDocs 的核心特性与适用边界MkDocs 是 2014 年诞生的开源项目用 Python 编写核心逻辑其实不复杂读取 docs 目录下的 Markdown 文件按照 mkdocs.yml 配置文件里定义的导航结构和主题模板渲染成完整的静态站点。它的特性可以总结成四个字轻、快、稳、简。轻本身依赖极少一套 Python 环境就能跑起来。快构建速度非常快几百个文档页面的站点也是秒级构建。稳生成的是静态文件不涉及服务端脚本执行天然不容易出问题。简配置文件就一个 mkdocs.yml所有站点的骨架和外观都在这一个文件里定义。适用场景上MkDocs 最适合以文档为核心内容的项目项目文档、开发手册、知识库、API 文档、团队 Wiki。它不适合做博客没有现成的博客时间线体系、不适合做 CMS 内容管理没有后台管理界面也不适合做需要用户登录交互的站点。选型之前先想清楚自己的需求属于哪类能省掉后面不少折腾。1.3 和同类工具的横向对比当时我其实还看了另外三个方案GitBook、Docsify、Sphinx。简单说下我对比后的感受。工具语言/运行时渲染方式优点缺点MkDocsPython构建时渲染为静态 HTML轻量、配置简单、Material 主题颜值高生态插件不如 Sphinx 丰富GitBookNode.js本地构建静态站点界面简洁、Git 集成好新版商业化严重老版本维护停滞DocsifyNode.js运行时动态渲染无需构建改 Markdown 即刷新SEO 差首次加载慢依赖 JSSphinxPython构建时渲染静态 HTML功能强大适合代码级 API 文档配置复杂入门曲线陡峭这里面我重点说一下为什么排除 Docsify。Docsify 的无需构建看起来很诱人但它是在浏览器端动态解析 Markdown 渲染页面搜索引擎对它的爬取效果天然吃亏而且首屏性能受文档体积影响很大。MkDocs 是构建时生成 HTML每个页面都是真实存在的文件对 SEO 友好访问速度也快得多。如果你的文档站以后要面向搜索引擎引流MkDocs 会是更靠谱的选择。2. Python 环境与 MkDocs 工具链的安装细节2.1 检查系统自带的 Python 版本MkDocs 目前要求 Python 3.8 以上。我部署的这台机器是 Ubuntu 22.04 LTS 系统自带的是 Python 3.10完全满足要求。建议你动手前先确认一下服务器上的 Python 版本免得装到一半才发现版本过低。python3 --version pip3 --version如果你用的是 Ubuntu 20.04 或 CentOS 7 这类自带 Python 版本偏低的系统有两种做法一是用 apt/yum 升级系统 Python二是用 pyenv 装一个独立的 Python 版本。我个人更推荐 pyenv因为它不会动系统自带的 Python避免影响系统组件对原有 Python 的依赖。不过大多数情况下新装的主流 Linux 发行版自带的 Python 3.8 都够用。顺带一提检查完 Python 后最好看一眼系统时间是否准确。我在一次部署中就遇到服务器时间漂移导致 SSL 证书验证失败、pip 安装报错的事。如果date命令显示的时间和实际时间差太多先用sudo ntpdate或者启用 chrony 同步一下再继续下面的步骤。2.2 用虚拟环境隔离 MkkDocs 依赖这里我一直坚持的实践是任何 Python 应用都用 venv 虚拟环境安装绝不直接装到系统全局。原因很简单pip 直接往系统里装包时间长了必然会出现依赖冲突。今天装的 A 包需要某个库的 1.x 版本明天装的 B 包要求这个库升级到 2.x系统的 Python 环境就被搅乱了。创建虚拟环境的命令如下sudo apt update sudo apt install python3 python3-venv python3-pip -y mkdir -p ~/projects/docs-site cd ~/projects/docs-site python3 -m venv venv source venv/bin/activate执行source venv/bin/activate后命令行前面会出现(venv)标记说明你已经进入了虚拟环境。此后用 pip 安装的所有包都会装到这个环境目录里跟系统 Python 完全隔离。这个操作习惯能帮你挡掉后续 80% 的依赖问题。2.3 安装 MkDocs 与 Material 主题MkDocs 本身只是基础框架实际用的时候几乎都会搭配第三方主题。社区里最流行、我个人最推荐的是 mkdocs-material它被称为MkDocs 的最佳主题并不夸张——现代化外观、响应式布局、暗色模式、搜索高亮、通知组件、社交分享等常用能力全都内置了一个主题包能顶一整套插件组合。安装命令pip install --upgrade pip pip install mkdocs mkdocs-material国内服务器如果下载慢可以用清华 PyPI 镜像加速。我自己第一次在腾讯云上装的时候默认源下载速度只有几十 KB/s换了镜像之后直接拉满。pip install -i https://pypi.tuna.tsinghua.edu.cn/simple mkdocs mkdocs-material想一劳永逸的话还可以配置全局 pip 源pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple安装完成后验证一下版本mkdocs --version2.4 初始化 MkDocs 项目结构MkDocs 提供了一个脚手架命令mkdocs new能帮你生成最基础的项目骨架。但要注意它只生成一个 index.md 和 mkdocs.yml是个非常朴素的起点。cd ~/projects/docs-site mkdocs new .生成的目录结构长这样docs-site/ ├── docs/ # 存放所有 Markdown 源文件 │ └── index.md # 站点首页 └── mkdocs.yml # 站点配置文件核心逻辑很简单docs 目录是内容区mkdocs.yml 是控制区。你后续写文档就是在 docs 目录下添加 Markdown 文件站点怎么组织、怎么展示则由 mkdocs.yml 决定。3. mkdocs.yml 配置详解把站点结构和外观定下来3.1 基础配置项逐行说明mkdir 后你会发现 mkdocs.yml 初始内容非常简单只有一个 site_name。但这个文件才是整个站点的心脏常用的配置项远远不止这一个。我把自己实际用的一份配置模板拆开讲site_name: 项目文档中心 # 站点名称显示在浏览器标题和导航栏 site_description: 团队内部项目文档统一管理 # 站点描述用于 SEO 元信息 site_url: https://docs.example.com # 站点最终对外访问的 URL repo_name: docs-site # 显示在导航栏的仓库名 repo_url: https://github.com/you/docs-site # 关联的 Git 仓库地址如果走 Git 工作流site_url这个配置很多人会漏掉但它影响搜索结果和 sitemap 生成。如果你以后要对接搜索引擎优化务必在部署之前就填上最终要使用的域名不然后面生成的 sitemap 链接会带着127.0.0.1之类的内网地址改起来很麻烦。3.2 导航结构的设计与配置导航 nav 是 MkDocs 配置里最需要花心思的部分。它的作用是把 docs 目录下的 Markdown 文件组织成侧边栏菜单。默认情况下 MkDocs 会按照文件系统的目录结构自动生成导航但自动生成的效果通常不是我们想要的——文件排序、层级归属都不一定合理。显式配置 nav 才靠谱nav: - 首页: index.md - 快速开始: - 环境准备: getting-started/env.md - 创建第一个项目: getting-started/first-project.md - 用户指南: - 安装部署: guide/installation.md - 配置说明: guide/config.md - 开发者文档: - API 参考: dev/api.md - 架构设计: dev/architecture.md这里有个很关键的设计经验文件路径和导航层级不需要一一对应。nav 里的层级完全由你写出来的结构决定与磁盘目录无关。我推荐把导航层级控制在两层以内超过两层的嵌套会让侧边栏显得很深阅读体验明显下降。文档组织规划阶段先在纸上画好导航树再建目录和写文件比边写边改高效得多。3.3 主题参数与外观调优Material 主题的可配置项非常丰富我挑几个最影响观感的重点展示theme: name: material # 指定主题 language: zh # 界面语言设置为中文 features: - navigation.sections # 侧边栏按分区折叠显示 - navigation.expand # 默认展开所有分组 - navigation.top # 页面右下角显示返回顶部按钮 - content.code.copy # 代码块右上角显示复制按钮 - search.suggest # 搜索框提供搜索建议 - search.highlight # 搜索关键词高亮 palette: - scheme: default # 亮色模式配色 primary: indigo # 主题色 accent: indigo # 强调色 - scheme: slate # 暗色模式配色 primary: indigo accent: indigo font: text: Noto Sans SC # 正文使用思源黑体对中文显示更友好 code: JetBrains Mono # 等宽字体用于代码展示features列表里每一项对应一个交互特性。比如navigation.sections会让侧边栏的分组标题变成区域分隔块视觉上比平铺的列表清晰很多content.code.copy则是给所有代码块加了个复制按钮实用价值极高。palette同时配置了亮色和暗色两套方案用户端会自动跟随系统偏好切换这个功能现在几乎成了标配。3.4 常用插件与 Markdown 扩展Material 主题自带搜索能力但很多高级特性还需要额外插件来扩展。我当前在用的插件组合如下plugins: - search # 内置搜索必须保留 - git-revision-date-localized: # 显示文档最后更新时间 type: date - minify: minify_html: true # 压缩 HTML 输出 minify_js: true # 压缩内联 JS minify_css: true # 压缩内联 CSS markdown_extensions: - admonition # 支持警告/提示块语法 - toc: permalink: true # 标题右侧生成锚点链接 - pymdownx.highlight: anchor_linenums: true # 代码行号 - pymdownx.superfences # 增强代码块渲染 - pymdownx.tabbed: alternate_style: true # 标签页切换样式 - pymdownx.tasklist: # 支持任务清单 [ ] / [x] custom_checkbox: true其中admonition扩展特别值得推荐它让你在 Markdown 里写带颜色边框的提示块 注意生产环境部署前务必先配置好 HTTPS 证书。配合自定义标题语法还能写出注意警告成功等不同风格的提示框做新人文档时尤其好用。注意对应语法是!!! note我上面用这种写法的其实是普通引用块要区分开。MkDocs 默认支持一套名为GitHub Flavored Markdown的语法子集加上 pymdownx 系列扩展后你几乎可以用到所有主流的 Markdown 增强语法——表格、任务列表、代码高亮、数学公式、时序图都能覆盖。这些扩展不用额外安装它们随 Material 主题一起被打包了直接在配置文件里启用即可。4. 本地构建与预览上线前必须做好的验证4.1 使用 mkdocs serve 实时预览配置写好后第一件事不是急着上线而是先在本地跑起来看看效果。mkdocs serve会启动一个开发服务器默认监听 8000 端口而且支持热重载——你保存 Markdown 文件后浏览器里立刻就能看到更新不用手动刷新。mkdocs serve默认情况下监听的是 127.0.0.1只允许本机访问。如果想在局域网内用同一网络下的手机或另一台电脑预览效果可以指定监听地址mkdocs serve --dev-addr 0.0.0.0:8000这个命令在团队协作场景里特别实用——同事不用装任何环境打开浏览器输入http://你的IP:8000就能预览文档站。但要注意这只是开发预览模式性能优化、缓存策略、并发处理都不适合生产环境正式对外访问还是得用静态文件 Nginx 的方式。4.2 使用 mkdocs build --strict 做上线前构建预览确认界面和内容没问题后执行正式构建mkdocs build --strict--strict参数非常关键。它会把所有警告当作错误处理一旦文档中有链接失效、文件路径错误、语法问题构建立刻终止并报错。这个机制是文档质量的最后一道防线能阻止带着坏链接的文档被发布出去。构建完成后所有产出都在site/目录。这个目录就是完整的静态网站可以直接被任何 Web 服务器托管。检查一下产物ls -al site/如果发现site/里有可疑的过期页面可以随时用mkdocs build --clean清理后重建。实际上build命令默认就会清理旧产物所以不用特意加参数。4.3 把构建过程脚本化手动执行构建命令做一两次没问题但文档站是要持续维护的每次改完文档都手动跑一遍命令很容易忘。我把构建流程写成了一个简单的脚本放在项目根目录下#!/bin/bash # deploy.sh cd ~/projects/docs-site source venv/bin/activate mkdocs build --strict sudo rsync -av --delete site/ /var/www/docs-site/site/这里解释一下两步操作的含义mkdocs build负责生成最新静态文件到 site 目录rsync则把 site 目录整体同步到 Nginx 的托管目录/var/www/docs-site/site/。--delete参数保证目标目录里多出来的旧文件会被清掉避免出现旧页面还在被访问的混乱。脚本写好记得加执行权限chmod x deploy.sh以后每次更新文档只需要执行./deploy.sh这一个命令就完成了从构建到发布的全部流程。5. 外部访问落地Nginx 反代与端口放行实操5.1 外部访问方案分析静态托管还是反向代理文档站对外访问前先搞清楚自己的网络条件。如果服务器有公网 IP 和已备案域名直接上 Nginx 是最标准的做法如果服务器在内网没有公网 IP那就要考虑内网穿透工具或者使用云服务厂商提供的隧道能力。我的情况是有一台公网服务器加一个已备案的域名所以选了 Nginx 托管静态文件的方式这也是最稳妥、最可控的方案。这里要强调一个架构选择MkDocs 构建出来的静态文件应该直接交给 Nginx 做静态托管而不是让 Nginx 反代到mkdocs serve的端口。很多人第一次折腾时会误以为要在服务器上开着mkdocs serve才能访问其实完全没必要。静态托管性能更好、配置更简单、也更安全——不需要常驻一个 Python 进程少一个攻击面。5.2 Nginx 安装与基础配置我的服务器是 Ubuntu 系统安装 Nginx 用 apt 一条命令搞定sudo apt install nginx -y安装完成后先确认服务运行正常sudo systemctl status nginx然后在 Nginx 的站点配置目录下新建一个配置文件我习惯把每个站点独立成一个文件方便管理和回滚sudo vim /etc/nginx/sites-available/docs-site配置文件内容如下server { listen 80; server_name docs.example.com; root /var/www/docs-site/site; index index.html; location / { try_files $uri $uri/ 404; } location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2?)$ { expires 7d; add_header Cache-Control public; } location ~ /\. { deny all; } }逐段解释一下root指向 MkDocs 构建产物的实际路径这里就是 rsync 同步的目标目录。try_files $uri $uri/ 404是 Nginx 的经典配置作用是先按请求路径找文件找不到就尝试目录还是找不到就返回 404。MkDocs 生成的 URL 是.html结尾的纯静态链接这个配置足以覆盖全部场景。第二个 location 给静态资源加了 7 天浏览器缓存文档站的图片、CSS、JS 基本不会频繁变动这个策略能明显提升访问速度。第三个 location 阻断所有以点开头的路径请求防止访问者碰运气翻到服务端的敏感目录。配置写好后创建软链接启用站点并重载 Nginxsudo ln -s /etc/nginx/sites-available/docs-site /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginxnginx -t是配置文件语法校验这一步务必执行如果语法错误直接 reload 会导致服务挂掉。5.3 防火墙与安全组的放行服务器装好 Nginx 监听 80 端口后还需要确认防火墙没有拦截外部流量。Ubuntu 系统自带的防火墙是 ufwsudo ufw allow 80/tcp sudo ufw allow 443/tcp sudo ufw status443端口是等会儿配置 HTTPS 证书要用的现在一并放行省得后面再操作一次。如果你用的是 CentOS/RHEL 系服务器防火墙命令不同对应是 firewalldsudo firewall-cmd --permanent --add-servicehttp sudo firewall-cmd --permanent --add-servicehttps sudo firewall-cmd --reload还有一类情况容易被忽略云服务器的安全组策略。阿里云、腾讯云、华为云这些平台即使服务器内部防火墙放行了安全组没放行外部依然无法访问。登录云控制台找到实例的安全组配置确认入方向允许 80 和 443 端口。我遇到过一次完全相同的症状服务器本地 curl 一切正常外部浏览器访问超时排查到最后就是安全组没放行。5.4 HTTPS 证书配置用 Certbot 一条命令搞定HTTP 明文传输在现代环境下显然不够安全尤其是文档站可能涉及内部系统的部署细节。配置 HTTPS 证书用的是 Lets Encrypt Certbot 这套公认的标准方案免费且自动续期。首先安装 Certbot 的 Nginx 插件sudo apt install certbot python3-certbot-nginx -y然后执行一条命令Certbot 会自动检测 Nginx 里配置的域名完成证书申请和 Nginx 配置改写sudo certbot --nginx -d docs.example.com过程中它会问是否将 HTTP 自动重定向到 HTTPS选 2Redirect即可。申请成功后Cerbot 会生成一条自动续期的定时任务。验证一下续期任务是否存在sudo systemctl list-timers | grep certbot看到certbot.timer出现在列表里就说明自动续期已经生效。后期基本不需要人工干预证书到期前会自动续期并 reload Nginx。5.5 内网穿透没有公网 IP 时的备选方案如果你的服务器跑在内网没有公网 IP也没有云厂商提供的隧道服务那考虑内网穿透方案。业界常用的是 frp 和 ngrok 这类工具它们本质上是把内网服务的端口映射到一台有公网 IP 的中转服务器上。我在测试环境用过一段时间的 frp稳定性还可以但用起来涉及公网中转服务器的带宽和延迟体验不如直连。这个方案的具体配置涉及你用的中转服务器情况每家情况不一样就不展开写详细步骤了。把大原则说一下子穿透方案只适合临时演示或低访问量的场景正式团队的文档站建议还是搞一台有公网 IP 的轻量服务器成本不高但省下的是长期维护的心力。6. 上线之后安全加固、更新流程与踩坑清单6.1 文档站的安全加固要点站点上线后我第一时间做了几件事来加固安全性。第一件是给系统做基本加固因为暴露在公网的服务器永远在被扫描这是常态不是特例。最简单的操作是修改 SSH 默认端口、禁用 root 密码登录、配置 fail2ban 防暴力破解。这些措施和文档站本身没有直接关系但是服务器安全是所有在上面跑的服务的共同地基。第二件事是针对文档站本身的加固。如果只是面对站内用户可以为 Nginx 加上基础访问认证。生成一个密码文件sudo apt install apache2-utils -y sudo htpasswd -c /etc/nginx/.htpasswd admin然后在 Nginx 配置的 server 块里加上两行auth_basic Restricted Access; auth_basic_user_file /etc/nginx/.htpasswd;这样访问者必须输入用户名密码才能看到文档站内容适合文档只在团队内部开放的场景。如果你的文档站要面向外部公开访问跳过这一步即可。第三件事是定期备份。静态文件的备份策略非常无脑一条 rsync 就能搞定rsync -av /var/www/docs-site/site/ backup-server:/backup/docs-site/建议把这条命令加进 crontab每天自动执行一次。静态站点的备份恢复成本极低但没备份的话出问题时就只能欲哭无泪了。6.2 文档更新的两种工作流上线后的常态工作是更新文档。我总结了两种顺手的工作流按团队情况选择。第一种是Git Webhook 自动构建。文档源文件存放在 Git 仓库推送 main 分支后通过 webhook 触发服务器拉取最新代码并执行构建脚本。这种流程适合文档更新频繁、有多位协作者的团队。实现方式不复杂在 GitHub/GitLab 仓库配置 webhook 地址指向服务器上的一个接收脚本即可。第二种是手动拉取构建适合文档更新频率低、只有一两个人维护的场景。直接在服务器上执行cd ~/projects/docs-site git pull origin main source venv/bin/activate mkdocs build --strict sudo rsync -av --delete site/ /var/www/docs-site/site/我把这个流程打包成了deploy.sh脚本每次更新就只需跑这个脚本。要么用 Git 仓库统一管理要么直接在服务器上编辑 Markdown 文件再执行脚本两种方式都行关键是定下来后团队所有人按同一个约定执行。6.3 常见故障排查从症状到根因踩坑是免不了的我把这几个频率最高的问题连同排查思路列出来供参考。症状一访问站点返回 502 Bad Gateway这是典型的反代模式配置问题。如果你没有按我前面说的静态托管方式而是用 Nginx 反代到了某个端口502 说明 Nginx 连接不到后端进程。要么是mkdocs serve根本没在运行要么是端口配置不一致。排查命令ps aux | grep mkdocs sudo nginx -t tail -f /var/log/nginx/error.log症状二访问返回 404404 大多是 root 路径配置不对。检查 Nginx 的 root 是否指向了包含index.html的 site 目录。有时候 rsync 目标少了一个层级比如root /var/www/docs-site/而不是/var/www/docs-site/site/就会导致找不到文件。症状三CSS 样式全部丢失MkDocs 生成的 HTML 里引用的是绝对路径资源比如/assets/stylesheets/main.css前提是 site_url 配置和实际访问路径一致。如果你直接把静态文件放在某个子路径下访问而 site_url 还是根域名就会出现样式全丢。解决方法是让 site_url 和实际访问 URL 保持一致或者改用use_directory_urls: false调整 URL 生成策略。症状四中文内容乱码现在新版 MkDocs 默认 UTF-8 编码基本不会乱码但 Nginx 层面还是建议显式声明字符集省得某些边缘浏览器出现解析错误charset utf-8;6.4 我实际踩过的几个小坑除了上面几个常规问题还有一些更隐蔽的坑想单独提醒一下。一个是rsync 的 --delete 参数用错目录。我最早把目标目录写成/var/www/docs-site/而不是/var/www/docs-site/site/结果 rsync 把 Nginx 配置目录也清掉了一部分差点酿成事故。后来我把脚本里所有路径都改成了绝对路径并仔细确认了 rsync 的目标层级再也没出过问题。部署脚本里凡是涉及删除操作的命令路径一定要反复核对这是最基本的肌肉记忆。另一个是构建脚本忘记激活虚拟环境。如果你用 crontab 定时执行构建命令注意 crontab 的环境变量和交互式 shell 不一样。直接在 crontab 里执行mkdocs很可能提示找不到命令因为虚拟环境没有激活、PATH 里也没有 mkdocs。我在 crontab 里写的命令是/bin/bash ~/projects/docs-site/deploy.sh让脚本内部自己激活虚拟环境就不会受 crontab 的环境变量影响。还有一个是Nginx 的 open_file_cache 不更新。如果你用 Nginx 托管静态文件更新文档后偶尔会看到旧内容这通常是浏览器缓存导致跟服务端无关。如果要彻底避免可以在更新部署后主动让 Nginx 重新打开文件句柄或者在 Nginx 配置里对 html 文件设置较短的缓存时间。我的处理是 html 文件不设浏览器缓存只对 css/js/img 这类带 hash 的资源做长缓存效果很好。6.5 往深了扩展多语言、版本化与站点搜索增强基础站点跑通之后MkDocs 的能力还远不止于此。Material 主题内置了多语言支持在 mkdocs.yml 里配置alternates就能实现中英文等多语言切换。如果你们团队的目标用户有多语言需求可以在架构规划阶段就留好这个口子后续扩展时不需要重新设计文档结构。版本化文档是另一个常见需求——发布对外 SDK 或软件产品时1.x 和 2.x 的文档经常要同时在线可查。MkDocs 没有内建的版本化能力但可以结合 Git 分支来管理。常规做法是每个版本分支各自构建出一个静态站点Nginx 按路径区分docs/v1/、docs/v2/这样。这个做法虽然略显原始但胜在架构简单可靠不需要引入额外组件。搜索方面默认的 search 插件对中文的支持能力有限我实测下来中文关键词的搜索体验一般。如果文档站的中文内容占比高可以考虑接入第三方搜索服务或者用 lunr 配合中文分词插件做增强。不过对大多数内部团队场景默认搜索已经够用了不必一开始就上重型方案。整个流程走下来我最深的体会是MkDocs 这套工具链的价值在于把写文档和发布文档之间的摩擦降到了极低。它不搞复杂的前端工程化体系不引入一堆构建依赖简简单单几个 Markdown 文件加一个配置文件配合 Linux 服务器上成熟的 Nginx就能得到一个体验不错的文档站。如果团队的技术栈本身就重度依赖 Markdown 和 Git 工作流部署一个 MkDocs 文档站甚至可以是项目知识管理的第一步——新人进来先看文档站的导航项目的全貌和约定就能快速对齐这比任何入职培训都高效得多。当然工具只是起点。文档站能不能真正发挥作用最终还是取决于有没有人认真维护内容。MkDocs 只是把维护文档这件事变得足够简单让维护者不再因为发布流程繁琐而拖延更新。如果你也在为团队文档的事头疼找台 Linux 服务器按这篇文章的步骤走一遍我相信你会对它爱不释手。

相关新闻

EMNLP 2026 Oral|HOMURA:面向时间受限场景的 LLM 翻译强化学习优化

EMNLP 2026 Oral|HOMURA:面向时间受限场景的 LLM 翻译强化学习优化

1. 概述 大语言模型(LLMs)在多语言翻译领域取得了显著进展,但普遍存在系统性的“跨语言冗长偏差”(Verbosity Bias),导致译文往往过于啰嗦,难以满足字幕翻译、视频配音等对时间预算(…

2026/10/11 8:23:28 阅读更多 →
金额存储为什么必须用decimal?从浮点精度到工程实践全解析

金额存储为什么必须用decimal?从浮点精度到工程实践全解析

半夜十二点的对账单,横竖差了三分钱。财务催得急,运维把日志翻了个底朝天,最后定位到一行代码:double amount price * quantity * discountRatio;——那一刻所有人都在骂娘,但这事儿真不能全怪写代码的人,…

2026/10/11 8:23:27 阅读更多 →
通达信指标黄金分割线分析技术支撑压力线

通达信指标黄金分割线分析技术支撑压力线

HH:HHV(HIGH,11); LL:LLV(LOW,11); HH1:BARSLAST((HH>REF(HH,1))); LL1:BARSLAST((LL < REF(LL,1))); DRAWTEXT(CROSS(HH1,LL1),90,众),COLORYELLOW; DRAWTEXT(CROSS(LL1,HH1),90,4),COLORCYAN; DRAWTEXT(CROSS(HH1,LL1),60,龙),COLORYELLOW; DRAWTEXT(CROSS(LL1,HH1),60…

2026/10/11 8:22:27 阅读更多 →

最新新闻

code-review-graph:AI 代码审查的「导航卫星」|SSP Github Daily

code-review-graph:AI 代码审查的「导航卫星」|SSP Github Daily

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 9:08:48 阅读更多 →
【Bug已解决】PyTorch CUDA error: an illegal memory access was encountered 解决方案

【Bug已解决】PyTorch CUDA error: an illegal memory access was encountered 解决方案

【Bug已解决】PyTorch CUDA error: an illegal memory access was encountered 解决方案 问题描述 在 PyTorch 中使用 GPU 进行深度学习训练时&#xff0c;开发者可能会遇到最令人头疼的错误之一&#xff1a; CUDA error: an illegal memory access was encountered这个错误通常…

2026/10/11 9:08:48 阅读更多 →
REA模型:用资源-事件-参与主体重塑企业业务数据建模

REA模型:用资源-事件-参与主体重塑企业业务数据建模

看到“rea”这个标题&#xff0c;我第一反应是把它补全成 REA——Resource-Event-Agent&#xff0c;也就是资源、事件、参与主体。这不是三个单词的简写&#xff0c;而是我做企业信息系统设计和数据建模时绕不开的一套核心方法论。如果你也在和订单表、流水表、明细账表打交道&…

2026/10/11 9:08:48 阅读更多 →
Java线程并发编程实战:协作、线程池与死锁排查全解析

Java线程并发编程实战:协作、线程池与死锁排查全解析

1. 友谊的前提&#xff1a;线程不是玄学&#xff0c;是与你程序“合伙过日子”的一群人“线程间的友谊小船”——我最初看到这个标题时&#xff0c;心里咯噔一下。做了十来年并发编程&#xff0c;最深的体会就是&#xff1a;线程之间的“友谊”确实存在&#xff0c;而且极其容易…

2026/10/11 9:08:48 阅读更多 →
Agent 记忆库实战:用 SQLite 构建持久化对话记忆系统

Agent 记忆库实战:用 SQLite 构建持久化对话记忆系统

1. 从内存到磁盘&#xff1a;为什么 Agent 需要一个真正的记忆库做前端出身的人&#xff0c;对“状态”这个词不会陌生。React 里有 useState、Redux 里有 store、Vue 里有 reactive&#xff0c;我们习惯了把数据放在内存里&#xff0c;页面刷新就重置&#xff0c;组件卸载就销…

2026/10/11 9:08:48 阅读更多 →
Django开源项目运行与代码解读全流程实战指南

Django开源项目运行与代码解读全流程实战指南

上周我交掉了Django的第二次作业&#xff0c;题目是“开源项目运行&解读”。本来以为只是把GitHub上某个项目clone下来、跑通、照着文档念一遍就算完事&#xff0c;结果真正动手才发现&#xff0c;一个开源Django项目从“能打开”到“能讲清楚”&#xff0c;中间隔着一大堆…

2026/10/11 9:07:47 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介&#xff1a;基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码&#xff0c;面向计算机相关专业课程设计与期末大作业学生&#xff0c;以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程&#xff0c;…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程&#xff1a;键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化&#xff0c;十个新手有八个栽在"往输入框里填东西"这件事上&#xff1a;要么填不进去&#xff0c;要么填了一半&#xff0c;要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程&#xff1a;阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀&#xff1a;什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面&#xff0c;跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →