Docker Compose自托管实战:一台小鸡跑起密码管理器、RSS阅读器与书签站


导读:上一篇反代教程把“入口”的问题解决了,这篇解决“服务从哪来”。自托管(self-hosted)的乐趣在于:不依赖任何云厂商的账户,密码、订阅、书签这些私人数据全攥在自己手里。但手动装服务有三大痛:依赖装半天、升级怕弄坏、迁移要重头来。Docker Compose把这三件事全变成配置文件:每个服务一个yaml,一条命令起停,一条命令升级,一条命令打包带走。这篇从零讲起,用一台1G内存的小鸡实际部署三个高频自托管应用——Vaultwarden密码管理器、FreshRSS阅读器、Linkding书签站,全程可照抄。


一、为什么是Docker Compose,而不是裸装或面板


先回答一个高频疑问:宝塔、1Panel这些面板也能一键装应用,为什么还要学Compose?


三个理由。其一,可迁移:面板装的服务绑死在面板上,Compose部署的服务就是一组容器加一份数据目录,换机器时整个文件夹rsync过去,up一下满血复活。其二,可版本化:docker-compose.yml是一个纯文本文件,放进Git仓库,你的整套基础设施就有了版本历史,改坏了随时回退。其三,不污染宿主机:每个应用的依赖全封在容器里,宿主机永远干净,应用之间互不干扰。


Compose的思维方式也很简单:一个服务(service)等于一个容器,加上它的镜像、端口、环境变量、数据卷(volume)。把这些写进一个yaml,Compose负责拉镜像、建网络、启容器、设重启策略。


二、环境准备:装Docker,规划目录


SSH连上小鸡,装Docker和Compose插件(官方脚本,Debian/Ubuntu通用):


curl -fsSL https://get.docker.com | sh


验证:docker --version 和 docker compose version 都有输出即可。


第二步,目录规划,这一步决定以后乱不乱。约定一个根目录,每个应用一个子目录,数据统一放子目录下的data里:


/opt/selfhosted/

vaultwarden/ (docker-compose.yml + data/)

freshrss/ (docker-compose.yml + data/)

linkding/ (docker-compose.yml + data/)


以后要迁移,tar打包 /opt/selfhosted 整个目录就完事。


三、第一个服务:Vaultwarden密码管理器


Vaultwarden是Bitwarden服务端的开源轻量实现,Rust写的,内存占用常年在50M以内,个人用绰绰有余。它管着你的全部密码,所以部署时有两件事必须做对:数据落盘、绑定本机。


进入目录写 docker-compose.yml:


services:

vaultwarden:

image: vaultwarden/server:latest

container_name: vaultwarden

restart: unless-stopped

environment:

- DOMAIN=https://pw.example.com

- SIGNUPS_ALLOWED=true

volumes:

- ./data:/data

ports:

- '127.0.0.1:8222:80'


逐块解释。image:用哪个镜像,latest跟随官方更新。restart: unless-stopped:开机自启、崩溃自动拉起,这行是服务“稳”的关键。environment里的DOMAIN要填你最终访问它的域名(配合上篇的反代),SIGNUPS_ALLOWED控制是否开放注册——自己注册完账号后建议改成false再重启,防止陌生人注册。volumes把容器内的/data挂到宿主机当前目录的data文件夹,数据库、附件全在里面,容器删了数据还在。ports只绑127.0.0.1:8222是刻意为之,外网摸不到它,只有本机的Nginx能转发进来。


启动:


docker compose up -d


看状态:docker compose ps 显示running即成功。浏览器配好反代后访问 https://pw.example.com ,注册账号,装上浏览器插件,手机App填上自建服务器地址,全平台同步就通了。


两个使用提醒:第一,Vaultwarden的管理入口在 /admin,首次访问会让你设置管理令牌,设一个强口令;第二,主密码是唯一解密钥匙,服务器上存的全部是加密数据,主密码丢了谁也救不了,务必记在物理介质上。


四、第二个服务:FreshRSS阅读器


信息焦虑年代,RSS是把主动权拿回来的工具:不靠算法投喂,自己订阅、自己排序、读完即走。FreshRSS是PHP生态里最省资源的全功能阅读器之一,支持全文抓取、多用户、各种客户端API。


services:

freshrss:

image: freshrss/freshrss:latest

container_name: freshrss

restart: unless-stopped

environment:

- TZ=Asia/Shanghai

- CRON_MIN=13,43

volumes:

- ./data:/var/www/FreshRSS/data

- ./extensions:/var/www/FreshRSS/extensions

ports:

- '127.0.0.1:8080:80'


两个新知识点。TZ环境变量:容器默认是UTC时区,不改的话定时任务会在你以为的时间点错开八小时执行。CRON_MIN指定内置刷新任务的分钟数(这里每小时第13和43分抓取订阅源),错开整点可以避开订阅源的高峰。extensions目录单独挂出来,方便手动装插件。


up起来、反代配好后打开网页,按向导初始化:选SQLite数据库(个人订阅量几百个源以内完全够用)、建管理员账号,然后开始添加订阅。进设置把“允许API”打开(给手机客户端Reeder、FeedMe等使用),一个私人版阅读器就成了。


实操经验:给每个订阅源开启“抓取全文”(源设置里勾选),很多博客只输出摘要,开全文后阅读体验天差地别;分类建好,用“收藏”功能代替稍后读应用,一物多用。


五、第三个服务:Linkding书签站


浏览器书签同步要么靠厂商账户,要么靠插件,总有各种限制。Linkding是个极简书签服务:加书签一秒、全文搜索、打标签,资源占用低到可以忽略,1G内存的小鸡带着它毫无感觉。


services:

linkding:

image: sissbruecker/linkding:latest

container_name: linkding

restart: unless-stopped

environment:

- TZ=Asia/Shanghai

volumes:

- ./data:/etc/linkding/data

ports:

- '127.0.0.1:9090:9090'


结构跟前两个一模一样。起来之后反代到 bookmark.example.com 之类的域名,注册个账号就能用。装上官方浏览器插件,网页上一键保存当前页;手机上用系统分享菜单扔过去。书签数据就是一个SQLite文件,躺在data目录里,备份策略极简。


三个服务跑起来之后,docker stats 看一眼:Vaultwarden约50M、FreshRSS约80M、Linkding约30M,加上系统开销,1G内存的小鸡还剩一大半。


六、日常运维:更新、备份、清理三板斧


自托管服务不是部署完就结束了,三件事做成习惯。


更新。Compose体系下的更新是标准三连:


docker compose pull

docker compose up -d

docker image prune -f


第一条拉新镜像,第二条用新镜像重建容器(数据卷不受影响),第三条清掉旧镜像释放磁盘。建议每个月做一次,安全补丁不拖。


备份。三个服务的命脉都在各自的data目录,所以备份就是备份 /opt/selfhosted。结合本站之前讲的restic异地备份,每天凌晨自动打包推走:


0 3 * * * tar -czf /tmp/selfhosted.tar.gz -C /opt selfhosted && restic backup /tmp/selfhosted.tar.gz && rm /tmp/selfhosted.tar.gz


恢复时解包到新机器同路径,docker compose up -d,全部服务原地复活。


清理。Docker用久了磁盘会被三样东西吃掉:悬空镜像、停止的容器、构建缓存。定期一条命令:


docker system prune -f


磁盘紧张的20G小鸡,这招能常捞回几个G。


七、小内存机器的取舍


不是所有应用都像这三个一样省。给小鸡排兵布阵时记住三个原则。


能SQLite就别上MySQL:数据库常驻内存动辄几百M,SQLite零开销,个人规模完全够。上面三个服务全是SQLite方案,这是它们适合小鸡的根本原因。


用 mem_limit 给贪吃的应用上笼子:compose里加一行 mem_limit: 300m,防止单个容器吃光内存拖死全家。


排好优先级:一台1G机器,跑这三个轻量服务没问题;再想加Nextcloud这种大户就该换2G内存的机器了,别硬塞。本站之前的小内存生存指南讲过的加Swap、砍占用,对容器化部署同样适用。


结语


到这篇为止,一台VPS就有了完整的“个人云”骨架:Nginx统一入口,Compose统一部署,密码、阅读、书签三大数据回归自己手中。这套架构的美妙之处在于可复制性——看中任何新的自托管应用,抄一段compose配置、建一个目录、起一个容器、配一条反代,五分钟纳入体系。数据在你手里,架构在你脑中,这就是自托管的全部乐趣。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

VPS搬家不丢数据:老机器迁到新机器的完整清单与回滚方案

Nginx反向代理实战:一台VPS托管你的全部服务,端口不再满天飞

评 论
更换验证码