用 Teemii + cpolar 搭建随身私人漫画库:Docker 部署与内网穿透实践
1. 项目缘起与整体设计思路1.1 从漫荒到私人藏书库的一次实践我猜很多人跟我一样收藏了一堆漫画资源散落在硬盘、网盘、旧手机里想找个系列的时候翻半天想用平板看却找不到合适的工具平台上的资源今天还在明天就下架。所谓的漫荒很多时候不是没有漫画看而是东西太多太乱真正想看的看不了。这其实是一个典型的本地资源管理问题。光是能存解决不了问题核心痛点在于三点统一的元数据整理、跨设备可访问、良好的阅读体验。我一开始也试过一些现成的方案要么是商业软件收费太高要么是数据格式绑死还有的在移动端体验极差。后来我决定自己动手用Teemii搭配cpolar整套搭建下来之后效果出乎意料地好。这套组合最终解决的是三个层面的问题Teemii负责把散乱的文件变成可检索、可分类、可阅读的数字书架cpolar负责把本地服务安全地映射到公网让我在外面也能连回家里的服务器最后的成果就是一个随身私人漫画库。这套思路不挑平台Windows、Linux、群晖都能用对硬件要求也不高。1.2 方案选型背后的关键考量做方案选型的时候我列过一个需求清单每条都对应一个现实痛点需求痛点来源选型关键点漫画格式兼容性手上有 CBZ、CBR、PDF、EPUB 等不同格式必须能统一识别并转档元数据自动整理手动重命名几千个文件不现实需要有刮削、匹配机制阅读进度同步手机看了第5话电脑要从第1话重翻需要一个中心化存储与管理端远程访问能力人在外面家里的服务器访问不到需要内网穿透或类似方案隐私与数据安全个人资源不希望经过第三方云端数据保留在本地穿透只映射流量选Teemii是因为它本身就是开源的Docker 部署足够轻量数据都落在自己的存储里不存在平台突然停止服务、数据被绑定的问题。选cpolar则是因为它的配置简单认证之后一行命令就能把本地端口暴露出去而且免费档位对个人用途来说完全够用。也有朋友问我为什么不用公网 IP 端口映射很简单大部分家庭宽带没有固定公网IP而且改路由、申请备案这套流程对于普通用户来说太不友好了。cpolar 这类内网穿透方案本质上是借助一条加密隧道把本地服务安全地接到一个公网入口上省去了复杂的网络配置。2. Teemii 核心功能与部署实操2.1 用 Docker 五分钟拉起 Teemii 服务我平时部署东西的习惯是能容器化就容器化Teemii 官方也推荐用 Docker 方式运行。你只需要准备一台常开的机器——哪怕是淘汰下来的旧笔记本或者小主机问题都不大。整体的安装思路是装 Docker写好 compose 文件拉镜像起容器完事。下面是一份我实际在用的docker-compose.yml关键参数都标注了用途version: 3.8 services: teemii: image: teemii/teemii:latest # 官方镜像amd64/arm64都覆盖 container_name: teemii restart: unless-stopped ports: - 127.0.0.1:3000:3000 # 仅本机映射后续用cpolar暴露 volumes: - ./data:/app/data # 数据库与配置数据 - ./library:/app/library # 漫画根目录也可以改成你实际的漫画存放路径 environment: - PUID1000 # 非 root 运行避免权限问题 - PGID1000 - TZAsia/Shanghai # 时区影响日志和元数据时间有一个细节值得展开说端口映射我特意绑定了 127.0.0.1而不是 0.0.0.0。这意味着 Teemii 只接受本机访问。这样做的考虑很简单——在没有额外鉴权的情况下直接把一个 Web 服务暴露在整个局域网里等于在自家 WiFi 上开了个后门任何人连上网络都能打开你的书架。所以我把公网入口完全交给 cpolar 管理本地端口不裸奔。这是很多教程不会告诉你的细节但非常关键。执行docker compose up -d之后浏览器访问http://localhost:3000首次打开会进入初始化引导它会让你设置管理员账号、指定漫画存储路径。这一步不用多想按向导走就行完成后整个服务就已经跑起来了。2.2 目录结构与数据组织策略Teemii 的数据目录结构并不复杂但组织方式直接影响后续管理效率。我见过有人把所有漫画往一个文件夹里一丢几万张图片混在一起结果光扫描就花了几个小时。合理的做法是建立按作者/作品名/卷册的层级目录library/ ├── 作者A/ │ ├── 作品X/ │ │ ├── Vol_001.cbz │ │ └── Vol_002.cbz │ └── 作品Y/ │ ├── 第01话/ │ │ ├── page_001.jpg │ │ └── page_002.jpg └── 作者B/ └── 作品Z/ └── 第01话.cbr我对目录的组织建议是保持清晰、稳定的层级结构命名尽量规范比如作品名 卷册号。Teemii 扫描的时候会把目录结构和文件名作为重要依据如果命名太随意刮削和匹配的成功率会明显下降。这一步做好后面省的是成倍的时间。扫描操作在界面的藏书管理入口里点击扫描之后Teemii 会读取目录结构识别漫画格式并生成一个基础的数据库条目。扫描速度取决于文件数量和存储介质机械硬盘几千个文件大概要几分钟SSD 上基本一分钟内搞定。2.3 元数据刮削与多来源匹配机制Teemii 的元数据刮削机制是它跟普通的文件管理器拉开差距的地方。它并不是简单地拿文件名充作标题而是会尝试从多个在线数据源去匹配作品封面、作者、简介、标签和章节信息。我之前手动整理书籍信息时每本书要花一两分钟去查资料、找封面而 Teemii 的效率则明显高出一个量级。实际使用中我发现匹配成功率受文件名规范程度影响极大。比如你给一个文件命名为1它可能什么都匹配不出来命名为作品名 Vol. 01或者作品名 第01话成功率就很高。如果某个条目匹配错了界面上也提供了手动修正入口可以搜索到正确的作品然后关联。这个功能我实测下来确实顺手整个元数据整理环节的体验称得上顺畅。还有一个彩蛋——Teemii 会为一些匹配不到元数据的中文作品保留本地信息也就是它会读取文件内部自带的书签或压缩包注释生成一个最小可用的条目。不至于因为刮削失败就变成孤儿文件这个兜底策略很踏实。3. 数据存储、阅读体验与特色功能实践3.1 数据库方案轻量但不简单的数据底座聊到数据存储Teemii 默认采用 SQLite这一点我觉得非常务实。有些同类系统上来就要求 PostgreSQL、MySQL对一个几百本漫画的家庭库来说明显是杀鸡用牛刀。SQLite 单文件存储、备份整体拷贝即可而且 99% 的查询场景响应都在毫秒级。实际过程中唯一需要留意的是数据库文件所在目录的写入权限问题。之前我在群晖上遇到过容器内 UID 和宿主机不一致导致服务时不时报只读错误的情况。解决方法也很简单——在 compose 里把PUID和PGID设为宿主机上对应目录所有者的 UID/GID重启容器就能解决。如果后期漫画量真的涨到万册级别SQLite 的写入并发可能会有瓶颈但对于个人使用完全够用。真要追求更夸张的规模Teemii 的架构也支持接入外部数据库不过那是极少数人的需求了。3.2 阅读器多端一致性的核心体验阅读器的体验直接决定这套系统的实用价值。Teemii 的 Web 阅读器在桌面浏览器、平板、手机浏览器上都能跑响应式布局做得比较细。我在 iPad 和安卓平板上都实测过纵向滚动模式和双页阅读模式都表现稳定。有一个细节必须提一下阅读进度同步是基于服务端的会话记录不是本地缓存。也就是说你在手机上读到第15页关闭之后到电脑上打开进度会从第15页继续。这背后的逻辑是Teemii 把阅读状态保存在数据库里任何终端都从服务端读取状态。这个功能解决了我在多个设备之间来回切换的阅读连续性痛点。3.3 导入工具的实战经验大多数人是已经有存量文件才想到搭私人漫画库。Teemii 的导入模块我用过几次之后总结了一个批量导入的高效流程推荐优先采用标准压缩格式CBZ/CBR如果手头是散图建议批量压成 CBZ 再入库。这样传输、读取效率都会提升。如果文件命名混乱建议先做一次批量重命名再去扫描。可以借助一些批量重命名工具把01_001这样的名字整理成作品名_第01话_01的体力活交给工具完成。比较推荐的扫描策略是分卷扫描即目录层级很深的藏书先扫顶层确认子结构正确再继续往下扫。一次扫全盘容易引发大量重复匹配请求拖慢速度。批量导入时Teemii 的扫描模块还会生成一份导入报告包含失败条目和原因。我在使用中发现绝大多数失败都源于文件名里的特殊字符比如中文冒号、问号、引号等。遇到这种情况批量清理文件名特殊字符然后重新扫描即可。4. cpolar 内网穿透与随身访问配置4.1 为什么选择 cpolar 做远程访问层服务搭好了书也整理好了如果只能在家里访问那就还差一口气。我个人的需求是通勤路上用手机看午休时用公司电脑看一两话如果窝在咖啡馆也希望打开平板就能连回家。这就意味着必须有一个稳定的远程访问链路。cpolar 这类工具的核心原理是借助部署在公网的跳板服务器建立一条数据隧道将本地某个端口这里是 3000映射成一个公网可访问的域名地址。关键在于数据流虽然经过第三方服务器但隧道本身带有加密而且 Teemii 的数据始终保存在本地不经过任何第三方存储。这跟把漫画传到公共网盘完全是两回事——后者你的数据在别人服务器上前者只是数据流的搬运通道。选 cpolar 还有一个现实原因配置成本低。认证之后它会分配一个随机域名免费档足够个人日常使用。付费档可以固定域名、增加带宽和隧道数量等确认自己能稳定用下来再考虑也不迟。4.2 从安装到映射的完整实操流程cpolar 的安装方式覆盖主流平台我这里以 Linux 服务端为例说明完整的配置流程# 安装Debian/Ubuntu 系 curl -L https://cpolar.cn/static/downloads/install-release.sh | sudo bash # 查看版本确认安装成功 cpolar version # 认证token 在 cpolar 网页后台的“认证”页面获取 cpolar authtoken xxxxxxxxxxxxxxxx # 启动一个隧道映射本地 3000 端口到公网 cpolar http 3000执行完成之后终端会输出一段公网访问地址把地址直接在手机浏览器打开就能看到 Teemii 的登录界面了。这里面有几个值得注意的细节第一cpolar 的免费隧道地址每次重启都会变化。如果你只是偶尔用用这个缺点还能接受如果每天都依赖它访问建议使用固定域名方案。固定域名之后域名不变访问体验会稳定很多。第二建议在守护进程里托管 cpolar而不是把它挂在一个会话终端里。官方提供了 systemd 服务可以这样启用systemctl enable cpolar systemctl start cpolar或者直接用cpolar start tunnel_name --log stdout这样的后台模式。这样做的意义在于服务器重启之后 cpolar 会自动恢复你不需要再跑到机房或者远程 SSH 登录去手动拉起隧道。第三隧道协议的选型。cpolar 支持 HTTP 和 TCP 两种隧道。对漫画库这种 Web 应用HTTP 隧道就够用了。如果你后续想加一些其他协议的本地服务比如 SSH 访问家里的 NAS才需要考虑 TCP 隧道。4.3 访问链路安全加固的实操经验把服务暴露到公网就意味着任何人拿到这个域名都有可能访问。所以有一件事必须做不要用 Teemii 的默认管理员口令。你初始化时设的密码强度直接决定整套系统的安全上限。我实际使用的加固策略包括三层首层是 Teemii 自带的账号密码登录这是第一道防线。第二层是使用 cpolar 的访问控制功能为公网域名额外加一层访问凭证即使有人拿到了域名也需要通过这层验证才能看到登录页。第三层是设备终端层面的习惯离开时随手退出登录不在公共电脑上勾选记住我。还有一个你们可能会忽略的细节Teemii 的管理端和阅读端是同一套服务没有独立的访客模式。所以如果分享给朋友看书架上的某些作品这意味着对方会拥有完整的管理权限。我的建议是要么只分享给绝对信任的人要么在服务端再跑一个只读的独立实例指向另一个书库。我个人在实践中倾向于只在家庭可信网络内分享公网访问则只留给自己使用。安全这个环节马虎不得毕竟一旦被攻破受影响的不是一部漫画的事情而是你整个家庭网络。5. 常见问题排查与体验优化实录5.1 问题速查表部署、导入、访问全链路我在整个搭建过程中踩过不少坑有一些问题非常典型几乎每个新手都会遇到。我把它们整理成了一张速查表现象可能原因解决办法容器启动后页面打不开端口冲突或者映射绑定有问题检查 3000 端口是否被占用docker logs teemii看日志扫描漫画后看不到书籍封面文件名不规范导致刮削匹配失败规范化文件命名手动修正元数据远程访问时页面加载很慢公网上行带宽不足或者隧道带宽受限压缩图片比例用流量高峰时段测试进度不同步同时开了多个页面或者缓存陈旧刷新页面关闭旧标签页重新登录提示数据库只读PUID/PGID 不匹配宿主机权限修改 compose 中的用户 ID 并重建容器cpolar 隧道地址变了免费随机域名重启变化升级固定域名方案5.2 一个印象深刻的实战排障过程我印象比较深的是一次奇怪的访问故障白天在公司用手机访问正常晚上回家连上 WiFi 反而打不开了。排查了半天发现问题根本不在 Teemii 和 cpolar 上——是家里 WiFi 路由器开了 AP 隔离导致局域网内的设备无法互访而我的手机恰好优先走了局域网 IP 去访问服务器。这个案例的启发是远程访问链路有问题不一定出在远端很多打不开的问题根源在本地网络。排查顺序非常重要我会按先本地后公网的顺序推进先确认本地http://localhost:3000是否正常再确认局域网 IP 能否访问最后才检查公网隧道状态。这样能快速定位绝大多数故障。5.3 性能调优给机械硬盘环境的建议如果你像我一样漫画库存放在 NAS 的机械硬盘上扫描和缩略图生成会比较慢。Teemii 处理缩略图的机制是扫描时生成封面预览缓存但如果文件很多第一次扫描会持续较长时间。我的建议是启用扫描任务的优先级机制把需要优先看的作品放到高层级目录第一轮扫描先覆盖这些其余的慢慢来。另一个优化方向是存储规划将系统数据数据库和缩略图缓存放在 SSD漫画原文件放在机械硬盘两者通过目录挂载组合起来。Teemii 支持的./data和./library分离设计正好方便这样操作。扫描速度和封面临时读取速度会显著提升而大文件读取延迟则被机械硬盘容量优势摊平了。6. 从实践出发的几条维护心得整套系统稳定运行几个月之后我总结了几条维护经验不一定适用于所有人但如果你想长期依赖私人随身漫画库这些建议值得参考关于备份策略。Teemii 的核心数据其实就是数据库和配置目录它们加起来可能只有几十兆。我每天用定时任务把data目录打包上传到独立的存储空间同时在本地留一份快照。漫画原文件则不再重复备份——它们本身就是从多个来源整理出来的丢了之后重新下载的成本远大于备份成本。这个取舍思路适用于任何个人服务优先保护不可再生的数据可再生的资源以重建代替备份。关于内容来源的合规性。搭建私人漫画库的前提是对自己收藏的资源有清晰的版权边界合理合法地使用技术工具不传播、不分享受版权保护的资源。我个人只将这套系统用于管理个人合法获取的内容并强烈建议所有读者都以此为前提。技术在搭建过程中是中性的使用者的自觉才是底线所在。关于服务更新。Teemii 迭代节奏比较快我基本上每个月会拉一次新镜像更新之前先看更新日志确认有没有破坏性变更。方法很简单docker compose pull之后docker compose up -d不到两分钟就能完成。cpolar 则不用频繁更新只要隧道状态正常就别手痒去动它。最后聊一个使用习惯上的体会随身漫画库的价值不在于囤了多少书而在于想看的时候三秒钟内就能打开。Teemii 把整理和检索的问题解决得很彻底cpolar 把访问半径扩大到了任何有网络的地方。整个过程里最大的成就感不是技术跑通了而是那些躺在旧硬盘里吃灰的漫画终于在手机和平板上活了过来。