Docsify 部署与问题排查完整笔记

一、查看 docsify-cli 版本

1.1 查看所有可用版本

使用 npm 命令查看 docsify-cli 的所有历史版本:

npm view docsify-cli versions

1.2 主要版本线

  • 4.x.x 稳定版:广泛使用的稳定版本系列,最新稳定版本为 4.4.4
  • 5.x.x 预发布版:下一代版本,处于候选发布阶段,适合测试新功能,不建议生产环境使用

1.3 在容器内查看版本

# 进入容器
podman exec -it docsify /bin/sh

# 查看版本
docsify --version
# 或
docsify -v

# 注意:docsify-cli -v 命令无效,应使用 docsify -v

二、部署文档遇到的核心问题

2.1 目录为空导致服务无法启动

问题现象:

No docs found /docs/index.html
Please run docsify init first.

原因:文档目录为空或缺少 index.html 文件。

解决方案:

# 清空目录并初始化
rm -rf /data/docsify/docs1/*
podman run --rm -it \
  -v /data/docsify/docs1:/docs \
  --entrypoint sh \
  localhost/zdocsify:2.0 \
  -c "docsify init /docs"

2.2 docsify init 提示文件已存在

问题现象:

. already exists.
✔ Are you sure you want to rewrite it? (y/N) true
Initialization succeeded! Please run docsify serve

但实际并未生成 index.html。

解决方案:确保目录完全为空,或手动创建 index.html 文件。


三、docsify-cli 参数支持问题

3.1 4.4.4 版本参数支持

docsify-cli 4.4.4 支持的参数:

  • --port, -p:监听端口
  • --livereload-port, -P:livereload 监听端口
  • --index-name, -i:自定义默认文件名
  • --open, -o:自动打开浏览器
  • --help, -h:显示帮助
  • --version, -v:显示版本

不支持的参数:

  • --host:不支持绑定到 0.0.0.0
  • --livereload:不支持关闭 livereload

3.2 5.0.0 版本参数支持

docsify-cli 5.0.0 新增支持的参数:

  • --host, -H:绑定到指定主机地址,支持 0.0.0.0

仍然不支持的参数:

  • --livereload:没有直接关闭 livereload 的参数

3.3 临时容器测试

如果目录空,需要初始化:

podman run --rm -it \
  --name docsify \
  --network znet \
  -p 3000:3000 \
  -v /data/docsify/docs1:/docs \
  --entrypoint sh \
  localhost/zdocsify:5.0 \
  -c "docsify init /docs"

再测试,0端口是随机生成,还是没禁用,禁用在index.html里脚本禁用,只浏览器不转圈了:

podman run --rm -it \
  --name docsify \
  --network znet \
  -p 3000:3000 \
  -v /data/docsify/docs1:/docs \
  --entrypoint sh \
  localhost/zdocsify:5.0 \
  -c "docsify serve /docs --port 3000 --host 0.0.0.0 --livereload-port 0"

四、livereload 问题处理

4.1 端口冲突问题

错误配置(禁止使用):

docsify serve /docs --port 3000 --host 0.0.0.0 --livereload-port 3000

说明:主服务端口与 livereload 端口不能相同,否则导致端口冲突,服务启动失败。

4.2 禁用 livereload 服务端

使用 --livereload-port 0 让系统分配随机端口:

docsify serve /docs --port 3000 --host 0.0.0.0 --livereload-port 0

执行后 netstat 查看效果:

tcp  0  0  0.0.0.0:3000  0.0.0.0:*  LISTEN  1/node
tcp  0  0  :::37245       :::*       LISTEN  1/node
  • 3000 端口:主服务正常监听
  • 37245 端口:livereload 使用的随机端口

4.3 页面仍然请求 livereload.js

问题现象:

GET https://domain:37245/livereload.js?snipver=1 net::ERR_CONNECTION_TIMED_OUT

原因:即使服务端使用 --livereload-port 0,页面中的客户端脚本仍然会尝试连接 livereload 服务。这是 docsify 5.0.0 的设计问题,livereload: false 配置并不能阻止客户端脚本的注入。

4.4 页面端禁用 livereload

在 index.html 中配置:

<script>
  window.$docsify = {
    name: '我的文档',
    livereload: false,
    // 其他配置...
  }
</script>

注意:此配置在 docsify 5.0.0 中可能不生效,页面仍会尝试加载 livereload.js。

4.5 使用 JavaScript 强制移除 livereload 脚本

在 index.html 中添加以下代码(在 docsify 脚本加载之后):

<script>
  (function() {
    // 移除已存在的 livereload 脚本
    function removeLivereload() {
      const scripts = document.querySelectorAll('script[src*="livereload"]');
      scripts.forEach(el => el.remove());
    }
    
    // 使用 MutationObserver 监控新增的脚本
    const observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        mutation.addedNodes.forEach(function(node) {
          if (node.tagName === 'SCRIPT' && node.src && node.src.includes('livereload')) {
            node.remove();
          }
        });
      });
    });
    
    observer.observe(document.documentElement, {
      childList: true,
      subtree: true
    });
    
    // 定期检查并移除(保险起见)
    setInterval(removeLivereload, 500);
    
    // 页面加载完成后立即执行
    document.addEventListener('DOMContentLoaded', removeLivereload);
    removeLivereload();
  })();
</script>

setInterval(removeLivereload, 500) 说明:每隔 500 毫秒执行一次移除函数,用于处理 docsify 核心脚本延迟注入 livereload 的情况。此定时器会持续运行直到页面关闭。

4.6 优化版:成功移除后停止监控

<script>
  (function() {
    function removeLivereload() {
      const scripts = document.querySelectorAll('script[src*="livereload"]');
      if (scripts.length > 0) {
        scripts.forEach(el => el.remove());
        observer.disconnect();
        clearInterval(intervalId);
        return true;
      }
      return false;
    }

    const observer = new MutationObserver(function(mutations) {
      for (let mutation of mutations) {
        for (let node of mutation.addedNodes) {
          if (node.tagName === 'SCRIPT' && node.src && node.src.includes('livereload')) {
            node.remove();
            observer.disconnect();
            clearInterval(intervalId);
            return;
          }
        }
      }
    });

    observer.observe(document.documentElement, { childList: true, subtree: true });
    const intervalId = setInterval(removeLivereload, 500);
    document.addEventListener('DOMContentLoaded', removeLivereload);
    removeLivereload();
  })();
</script>

五、谷歌字体加载超时问题

5.1 问题现象

GET https://fonts.googleapis.com/css2?family=Roboto+Mono... net::ERR_CONNECTION_TIMED_OUT

原因:服务器无法直接访问谷歌字体服务。

5.2 解决方案

使用国内 CDN 加载 vue.css,并覆盖字体设置:

<!-- 使用国内 CDN 加载 vue.css -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/docsify/4.13.0/themes/vue.css">

<style>
  /* 强制使用系统字体,避免请求谷歌字体 */
  body, input, button, textarea {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Microsoft YaHei", sans-serif !important;
  }
  code, pre, kbd, .markdown-section pre, .markdown-section code {
    font-family: "SF Mono", "Fira Code", "Consolas", "Liberation Mono", "Menlo", monospace !important;
  }
</style>

在 docsify 配置中指定字体:

<script>
  window.$docsify = {
    fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
  }
</script>

六、完整的 index.html 模板

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>我的文档</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="description" content="Description">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
  
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/docsify/4.13.0/themes/vue.css">
  
  <style>
    body, input, button, textarea {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Microsoft YaHei", sans-serif !important;
    }
    code, pre, kbd, .markdown-section pre, .markdown-section code {
      font-family: "SF Mono", "Fira Code", "Consolas", "Liberation Mono", "Menlo", monospace !important;
    }
  </style>
</head>
<body>
  <div id="app"></div>
  
  <script>
    window.$docsify = {
      name: '我的文档',
      repo: '',
      loadSidebar: false,
      subMaxLevel: 2,
      search: 'auto',
      livereload: false,
      fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
    }
  </script>
  
  <!-- 移除 livereload 脚本 -->
  <script>
    (function() {
      function removeLivereload() {
        const scripts = document.querySelectorAll('script[src*="livereload"]');
        if (scripts.length > 0) {
          scripts.forEach(el => el.remove());
          observer.disconnect();
          clearInterval(intervalId);
          return true;
        }
        return false;
      }

      const observer = new MutationObserver(function(mutations) {
        for (let mutation of mutations) {
          for (let node of mutation.addedNodes) {
            if (node.tagName === 'SCRIPT' && node.src && node.src.includes('livereload')) {
              node.remove();
              observer.disconnect();
              clearInterval(intervalId);
              return;
            }
          }
        }
      });

      observer.observe(document.documentElement, { childList: true, subtree: true });
      const intervalId = setInterval(removeLivereload, 500);
      document.addEventListener('DOMContentLoaded', removeLivereload);
      removeLivereload();
    })();
  </script>
  
  <script src="//cdnjs.cloudflare.com/ajax/libs/docsify/4.13.0/docsify.min.js"></script>
</body>
</html>

七、容器管理命令

7.1 基本操作

# 停止容器
podman stop docsify

# 删除容器
podman rm docsify

# 删除镜像
podman rmi zdocsify:5.0

# 进入容器
podman exec -it docsify /bin/sh

# 查看容器日志
podman logs docsify
podman logs -f docsify

# 重启容器
podman restart docsify

7.2 运行容器

前台运行(调试用):

podman run --rm -it \
  --name docsify \
  --network znet \
  -p 3000:3000 \
  -v /data/docsify/docs1:/docs \
  --entrypoint sh \
  localhost/zdocsify:5.0 \
  -c "docsify serve /docs --port 3000 --host 0.0.0.0 --livereload-port 0"

后台运行(生产环境):

podman run -d \
  --name docsify \
  --network znet \
  -p 3000:3000 \
  -v /data/docsify/docs1:/docs \
  --restart=unless-stopped \
  localhost/zdocsify:5.0 \
  sh -c "docsify serve /docs --port 3000 --host 0.0.0.0 --livereload-port 0"

7.3 网络管理

# 查看所有网络
podman network ls

# 查看网络详情
podman network inspect znet

# 创建网络
podman network create znet

八、端口规划建议

服务容器内端口宿主机端口说明
docsify 主服务30003000必须暴露,供 Caddy 等反向代理使用
docsify livereload随机或 35729不映射建议禁用或不对外暴露
Caddy80/44380/443反向代理 docsify

九、与 Caddy 配合的配置

Caddyfile 配置示例:

your-domain.com {
    reverse_proxy docsify:3000
}

注意:只需转发主服务端口 3000,无需转发 livereload 端口。


十、关键要点总结

  1. docsify-cli 4.4.4 不支持 --host 参数,5.0.0 支持
  2. 升级到 5.0.0 后,livereload 仍无法通过 --livereload false 关闭
  3. 使用 --livereload-port 0 可让 livereload 使用随机端口
  4. 页面端的 livereload 客户端脚本需要额外处理才能移除
  5. 谷歌字体超时需使用国内 CDN 并覆盖字体设置
  6. 主服务端口与 livereload 端口不能相同
  7. 使用 livereload: false 配置在 5.0.0 中可能不生效,需结合 JavaScript 移除脚本
  8. 网络配置中使用自定义网络 znet 便于容器间通信

标签: none

添加新评论