容器重建后浏览器登录态不丢失的挂载与改写方案

举报
yd_254065487 发表于 2026/10/29 05:22:05 2026/10/29
【摘要】 profile 挂到宿主机后登录态仍会丢,根因是 Chrome 的 session cookie。本文给出 sqlite 批量改写并在 entrypoint 启动前执行的完整做法。

现象:profile 挂载对了,重启后仍要重新登录

容器里跑浏览器做采集或自动化,第一步通常是把 --user-data-dir 指到宿主机挂载的卷上,以为登录态就此保住。结果 docker restart 之后打开页面,还是登录页;书签、历史、密码都在,唯独登录态没了。

问题不在挂载,在 cookie 本身。绝大多数站点的会话 cookie 不带 Expires 或 Max-Age,浏览器把它标记为 session cookie,只活在进程生命周期里。更麻烦的是 Chrome 退出时会用内存状态回写数据库,你在它运行期间改的过期时间,会被原样覆盖回去。

先确认 Cookie 文件到底在哪

Chrome 96 之后 cookie 库从 Default/Cookies 挪到了 Default/Network/Cookies。用旧路径会改到一个不再被读取的文件,脚本退出码是 0,但一点效果没有。进容器看一眼:

ls -l /profile/Default/Network/Cookies /profile/Default/Cookies

它是标准 SQLite,cookies 表里跟持久化相关的是三列:is_persistent、has_expires、expires_utc。session cookie 的特征就是这三列全为 0。

一条 SQL 把 session cookie 批量改成持久 cookie

expires_utc 不是 Unix 时间戳,是「1601-01-01 起的微秒数」,Chrome 全系沿用这个基准,和 Unix 纪元差 11644473600 秒。下面这条把目标域名的 session cookie 统一改成 30 天后过期:

UPDATE cookies SET is_persistent=1, has_expires=1, expires_utc=(CAST(strftime('%s','now') AS INTEGER)+11644473600+2592000)*1000000 WHERE is_persistent=0 AND host_key LIKE '%example.com';

2592000 是 30 天,改成 7 天用 604800。WHERE 里的域名条件别省,否则整个 profile 里所有站点的 cookie 都被拉长有效期,出问题很难查。

entrypoint 里的执行顺序才是关键

这条 SQL 必须在浏览器进程启动之前、在同一个 entrypoint 里串行执行。两种常见错法:

  • 用 docker exec 进已经跑起来的容器改库。Chrome 早把数据读进内存了,你改的是磁盘副本,它退出时照样覆盖回去。
  • 后台起一个 sidecar 去改,和 Chrome 抢同一个 SQLite 文件,轻则语句拿不到锁失败,重则把库写坏。

entrypoint.sh 按这个顺序写:

  • #!/bin/sh
  • set -e
  • DB=/profile/Default/Network/Cookies
  • [ -f "$DB" ] && sqlite3 "$DB" "UPDATE cookies SET is_persistent=1, has_expires=1, expires_utc=(CAST(strftime('%s','now') AS INTEGER)+11644473600+2592000)*1000000 WHERE is_persistent=0 AND host_key LIKE '%example.com';"
  • rm -f /profile/SingletonLock /profile/SingletonSocket /profile/SingletonCookie
  • exec google-chrome --user-data-dir=/profile --remote-debugging-port=9222

第五行的 rm -f 不能漏。容器每次重建 hostname 都不一样,profile 里残留的 SingletonLock 指向一个已经不存在的 hostname,Chrome 会认为有另一个实例正在使用这个 profile,弹出 profile appears to be in use 并拒绝启动。

容器重建后怎么验证登录态还在

  • 重建:docker rm -f chrome && docker run -d --name chrome -v /srv/chrome-profile:/profile browser:1.0
  • 查落盘结果:docker run --rm --entrypoint sqlite3 -v /srv/chrome-profile:/profile browser:1.0 /profile/Default/Network/Cookies "SELECT name, is_persistent, datetime(expires_utc/1000000-11644473600,'unixepoch') FROM cookies WHERE host_key LIKE '%example.com';" 用 --entrypoint 另起一个容器读,避免和正在跑的 Chrome 抢文件。
  • 看登录态:新容器起来后打开页面,能直接进已登录状态、不跳登录页,才算通过。

还不通过的话,先查 expires_utc 是不是仍为 0(说明 SQL 没命中,多半是 host_key 写错),再确认读的是不是 Default/Network/Cookies 这个路径。

两个容易忽略的坑

  • cookie 值是加密的。value 列通常为空,真实内容在 encrypted_value 里,Linux 下由 keyring 或回退口令派生的密钥加密。换基础镜像、换 keyring 策略后旧 cookie 解不开,表现为记录都在但站点依然要求登录,只能重新登录一次再跑一遍改写。
  • 别用 docker commit 固化登录态。cookie 会过期,站点也会因为 UA、IP 变化主动失效,profile 卷加上这条 SQL 才是可重复的做法。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。