马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
采集服务在裸机上跑了半年,没出过大事——直到换服务器那天:Python 版本对不上、cron 任务忘配、字体缺了导致报表乱码,迁移花了一整天。迁完我就把服务容器化了:换情况从「一天」变成「一条命令」。这篇记录容器化过程中的实践和坑。
第一步:写 Dockerfile
- FROM python:3.12-slim
- WORKDIR /app
- COPY requirements.txt .
- RUN pip install --no-cache-dir -r requirements.txt
- COPY app/ ./app/
- RUN useradd -r -u 1001 collector \
- && chown -R collector:collector /app
- USER collector
- CMD ["python", "-m", "app.collect"]
复制代码 三个细节:slim 底子镜像(够用、体积小)、依赖先于代码拷贝(代码改动不会让依赖层缓存失效)、非 root 运行(安全惯例,数据目次权限一并处理)。
requirements.txt 记得锁版本(requests==2.32.3 这种),否则某天上游更新,镜像构建直接炸——裸机上踩的「依赖漂移」,容器化后并不会自动消失。
第二步:状态外置(最重要的一条)
容器的原则是「可抛弃、可重建」——所以 SQLite 文件、日志、任何有状态的东西,都不能留在容器里:- # docker-compose.yml
- services:
- collector:
- build: .
- env_file: .env
- volumes:
- - ./data:/app/data # serp.db、logs 全在这里
- restart: unless-stopped
复制代码 ./data 挂到宿主机上,docker compose down 重建容器,数据纹丝不动。反过来说:如果你发现有文件必须留在容器里才能工作,那是个 bug,迟早会在重建时丢数据。
第三步:调度方式的选择
采集任务大多是「定时批量 + 偶然长跑」,调度有三种姿势:
方式做法适合容器内 cron镜像里装 cron/守护不推荐:日志和退出码都难管宿主机 cron + 一次性容器docker compose run --rm collector批量任务首选常驻 worker服务自己带调度循环需要常驻并发/队列时我用的第二种,宿主机 crontab 就一行:- 0 6 * * * cd /srv/collector && docker compose run --rm collector >> run.log 2>&1
复制代码 每次跑一个干净容器,跑完即退,退出码就是成败——这比在容器里养一个 cron 守护进程干净得多。
第四步:密钥从情况进,不进镜像
- # .env(不进 git)
- SERPBASE_API_KEY=xxx
复制代码 两个禁忌:别用 ENV/ARG 把 Key 写进 Dockerfile(docker history 能看到镜像层里的值);别把 .env 打进镜像(.dockerignore 里加一行)。
第五步:日志与健康检查
日志:让程序输出到 stdout,宿主机同一收:- logging:
- driver: json-file
- options:
- max-size: "10m"
- max-file: "3"
复制代码 不配上限的话,json-file 日志能把磁盘悄悄吃满——之前磁盘篇讲的坑,容器里换个情势再来一遍。
健康检查:别只测「进程活着」,要测「能力还在」——比如最近一次成功采集的时间:- healthcheck:
- test: ["CMD", "python", "-c",
- "import app.health, sys; sys.exit(0 if app.health.fresh(240) else 1)"]
- interval: 5m
- retries: 3
复制代码 踩坑记录
坑 1:数据留在容器里。 重建容器数据全没。volume 挂载是第一条纪律。
坑 2:时区不对。 容器默认 UTC:日志时间是 UTC、datetime.today() 是 UTC——本地跑没问题、容器里跑出来的「本日」差 8 小时。要么同一按 UTC 思考(存储层推荐),要么显式设 TZ 情况变量,别稀里糊涂。
坑 3:密钥进了镜像层。 ARG API_KEY + ENV API_KEY=$API_KEY 的写法,docker history 一览无余。密钥只交运行时情况。
坑 4:依赖没锁版本。 镜像构建某天突然失败,因为上游发了新版本。requirements.txt 固定到详细版本。
坑 5:root 跑容器。 数据文件权限全归 root,宿主机上想改都费劲。非 root + 目次 chown。
坑 6:迁移完忘了 crontab。 容器化解决了代码和情况,但「谁在几点触发」还是宿主机的事——迁移清单里加上 cron 这一项。
工程清单
- slim 镜像 + 依赖锁版本 + 非 root
- 状态全部外置(volume),容器可随时重建
- 批量任务用「宿主机 cron + run --rm」,别在容器里养 cron
- 密钥交运行时 env,.dockerignore 清除 .env
- 日志 stdout + 大小上限;healthcheck 测真实能力
- 时区显式声明(UTC 或 TZ),迁移清单含 cron
容器化的价值不在「时髦」,而在把「情况」变成「代码」:过去散落在服务器上的 Python 版本、依赖、字体、cron,现在都在 Dockerfile 和 compose 里,可审查、可重建、可迁移。对一个人的采集项目来说,这是性价比很高的一次工程化。
接口的鉴权方式(Key 走情况变量)在 SerpBase 官方文档 有阐明,配合容器化时注意别让密钥进镜像。你们的采集服务跑在裸机还是容器里?迁移时踩过什么坑?评论区聊聊。
免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |