导读:上一篇反代教程把“入口”的问题解决了,这篇解决“服务从哪来”。自托管(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配置、建一个目录、起一个容器、配一条反代,五分钟纳入体系。数据在你手里,架构在你脑中,这就是自托管的全部乐趣。


