既然不想招人,我就把所有的 SOP 封装进 Docker。今天把最后几个爬虫服务也打包成镜像推到了私有仓库,看着 `docker-compose up -d` 之后所有服务在 30 秒内全部拉起,心里那点因为疫情被困在家的烦躁,总算被一种冰冷的秩序感压下去了一点。招人?算了,去年招的那两个后端,一个天天跟我掰扯技术选型,另一个连 Nginx 反向代理都配不利索,最后项目黄了,人还得我赔钱送走。管理成本比技术债务可怕一万倍,我现在宁愿跟命令行和配置文件死磕。
封装的过程就是一次对过去三年所有“野路子”的清算。最早那个微信爬虫,用了一堆脆弱的 XPath 和正则,依赖特定版本的 ChromeDriver,环境变量设得一塌糊涂。每次换服务器都得重新配一遍,还动不动因为系统库版本不对就崩。现在全扔进 Dockerfile,从 Python 3.7 的基础镜像开始,`requirements.txt` 精确锁版,Chrome 用 `–no-sandbox` 参数固定下来,再把解析规则和代理 IP 池的配置文件通过 Volume 挂载进去。最关键的一步是把日志统一输出到 `stdout` 和 `stderr`,这样直接用 `docker logs` 或者 ELK 栈就能抓,再也不用 SSH 登录到每台机器上去翻 `nohup.out` 了。
横向扩展的逻辑其实简单到粗暴。核心就两点:无状态和配置外置。所有服务都不能在本地磁盘存任何会话或者数据,状态要么扔 Redis,要么写进中心数据库。配置文件,比如数据库连接字符串、API 密钥、第三方回调地址,全部用环境变量注入。这样,任何一台装了 Docker 的 VPS,我只需要把 `docker-compose.yml` 和 `.env` 文件拷过去,改一下 `.env` 里的服务器标识和可能有的特定参数,一条命令就能复制出一个完整的环境。
我在三台不同供应商的 VPS 上做了测试,一台腾讯云,一台搬瓦工,还有一台是朋友的闲置机器。用 Ansible 写了段简单的 Playbook,批量 SSH 上去安装 Docker 和 Docker-Compose,然后拉取镜像、启动服务。从零开始到服务全部可用,最快的一台只用了 7 分钟。这要是搁以前,手动配置,光解决各种“神奇”的依赖冲突和权限问题,没半天时间下不来。现在这种效率,意味着我可以根据流量压力,随时冷启动新的节点,或者把某个不稳定的服务整体迁移到另一台机器,成本几乎为零。
当然坑也没少踩。最大的问题是网络。微服务之间用自定义的 Docker network 通信没问题,但有些老服务调用了外部 API,对方有频率限制,而且是按源 IP 计数的。所有容器默认都走宿主机的出口 IP,一下子就把限制用爆了。后来不得不在 Docker-Compose 里给每个需要独立出口 IP 的服务配置 `network_mode: “service:[vpn-service]”`,让它们通过一个专门跑了代理容器的隧道出去,这才算解决。还有数据卷的权限,在 Linux 上好好的,一到某台 Mac 宿主机上就各种 `Permission denied`,最后发现是 UID/GID 映射的问题, Dockerfile 里加了 `USER` 指令明确指定非 root 用户才消停。
把这些都固化下来之后,我忽然有点理解那些大厂为什么热衷中台和 PaaS 了。本质上就是把人的不确定性封装掉,把能标准化的操作全部变成可重复执行的代码。我不需要另一个“我”来理解我这一套混乱的思维,我只需要一个绝对听话、不会抱怨、24小时待命的执行层。Docker 镜像就是我这个一人公司最核心的资产,是把我从具体运维里解放出来的“分身术”。
省下来的时间干什么?可能用来研究一下怎么用 GitHub Actions 给这些镜像做自动构建和安全扫描,或者,干脆去阳台抽根烟。毕竟,身体才是第一生产力,而最近这腰,坐久了是真疼。














