惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
博客园 - 司徒正美
Last Week in AI
Last Week in AI
Recent Announcements
Recent Announcements
Y
Y Combinator Blog
博客园 - 聂微东
M
MIT News - Artificial intelligence
博客园_首页
Jina AI
Jina AI
博客园 - 叶小钗
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
J
Java Code Geeks
F
Fortinet All Blogs
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
Vercel News
Vercel News
The Cloudflare Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
N
Netflix TechBlog - Medium
B
Blog
Google DeepMind News
Google DeepMind News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

BlogFinder

日常漫步 Vol.24 之漫步前山河 - 雅余 周报 #1-聊聊本周的收获 - Edwin's Blog 我的OpenCode必装插件与Skill Write Something 掌中之物未必在掌握之中 · CRIVU PiliNara,一个更顺手的 PiliPlus 分支 「NekoEcho」:做一个必有回响的猫娘主题博客 2026-05 书影音总结 简化博客主题 - 安迪 我第一次发布 npm 包 拾花小记#45:中考前的二三事 – 小改学习志 黛西花园5月游 #18 枇杷又熟了的五月月报 一些奇奇怪怪的需求?word仿方正书版的几个小操作 - Xiobb's Blog 0419 御温泉之旅 修复了一些bug,网站基本上趋于稳定了 - 新锐博客 又回到四十年前 如何定义成功 迷鹿屋2026已重新上线 科技冰火两重天+一周回顾 ${title} 热度退了,我反而用得更深了-咕咚同学 我到底该不该换个域名? 随身WIFI折腾记 - 安迪 博客撰写体验提升——hexo pro插件 为什么不用相机把屏幕上的接关密码拍下来? 国清寺与天台山 – Ouroboros ★★★★☆《挽救计划》——久违的经济上行感 - Davidの3号基地 删除右键“打开方式”里多余选项 第三周刊_No.53|一切都会被支付两次
基于 VS Code 远程开发的 GPU Docker 容器自动清理方案实践 ...
Algieba · 2026-06-02 · via BlogFinder

1. 业务场景与核心需求

运行环境:

  • 操作系统:Ubuntu 22.04
  • 开发工具:VS Code Remote-SSH
  • 容器环境:Rootless Docker (非 root 用户权限运行)
  • 业务场景:GPU 服务部署与模型调试

核心需求:

  1. 自动释放:开发者下班合上电脑(物理断网)后,经过一段缓冲时间(例如 10 分钟),系统需自动停止该用户运行的 Docker 容器。
  2. 状态保持:在缓冲期内若用户重新连接网络,容器资源需保持运行,重置倒计时。
  3. 多开支持:支持用户同时开启多个 VS Code 窗口或 SSH 终端,只有当所有连接均断开时才触发倒计时。
  4. 常驻白名单:提供快捷指令,允许用户在特定情况下(如长时间训练任务)关闭自动清理功能。

2. 初步方案与局限性分析

初步思路:依赖 .bash_logout
最初的设计是在用户的 ~/.bash_logout 文件中添加清理逻辑。即在脚本中设定 sleep 600 (10分钟),随后执行 docker stop

遇到的问题:物理断网不触发注销流程
在实际测试中发现,当在终端手动输入 exit 时,容器能按预期被清理。但当直接合上笔记本电脑物理断网时,脚本完全未执行。

原因剖析:
通过检查服务器的 /etc/ssh/sshd_config,发现未配置 SSH 心跳检测 (#ClientAliveInterval 0)。物理断网属于异常掉线,操作系统完全依赖底层的 TCP KeepAlive 机制来判定连接断开。这一过程通常耗时 15 到 30 分钟,超时后系统会直接强制销毁 sshd 进程。这种非“优雅退出”的机制导致 .bash_logout 中的逻辑被彻底跳过。


3. 方案演进:引入后台守护进程 (Daemon)

既然无法在“退出时”触发,方案需转向“持续监控”模式。我们决定在用户登录时,静默启动一个轻量级的 Bash 守护进程,通过轮询统计用户的 sshd 会话数量来判断在线状态。

遇到的问题:Rootless Docker 守护进程失联
编写好监控脚本并通过 nohup 投入后台运行后,发现虽然触发了超时清理逻辑,但 docker ps -qdocker stop 命令执行失败,系统日志提示无法连接到 Docker 守护进程。

原因剖析:环境变量丢失
在 Rootless Docker 模式下,普通用户终端能够正常使用 docker 命令,是因为用户通过 SSH 登录时,系统自动为其分配了如 XDG_RUNTIME_DIR 等关键环境变量,指向了 /run/user/<uid>/docker.sock
而通过 nohup 和脱机运行的后台守护进程,脱离了用户的 Login Shell 上下文,导致这些特定环境变量丢失。Docker 客户端退化到去寻找默认的系统级 /var/run/docker.sock,从而引发权限或找不到文件的错误。


4. 最终实现方案

明确了所有限制条件后,最终落地的方案由两部分组成:注入了环境变量的独立守护进程脚本,以及 ~/.bashrc 中的控制逻辑。

步骤一:创建守护进程脚本

在用户根目录下创建 ~/.gpu_cleanup_daemon.sh 脚本。
注意:脚本开头的环境变量可通过在正常终端中运行 env | grep -E "DOCKER|XDG" 获取,需将 1002 替换为实际的用户 UID。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/bin/bash





export XDG_RUNTIME_DIR=/run/user/1002
export DOCKER_HOST=unix:///run/user/1002/docker.sock


RAW_TIME=${GPU_CLEANUP_GRACE_PERIOD:-10m}
case $RAW_TIME in
*m) GRACE_SEC=$((${RAW_TIME%m} * 60)) ;;
*h) GRACE_SEC=$((${RAW_TIME%h} * 3600)) ;;
*s) GRACE_SEC=${RAW_TIME%s} ;;
*) GRACE_SEC=$RAW_TIME ;;
esac

ELAPSED=0
CHECK_INTERVAL=10

while true; do

if [ -f "$HOME/.skip_gpu_cleanup" ]; then
ELAPSED=0
sleep $CHECK_INTERVAL
continue
fi


SESSION_COUNT=$(pgrep -u "${USER}" -x sshd | wc -l)

if [ "${SESSION_COUNT}" -gt 0 ]; then

ELAPSED=0
else

ELAPSED=$((ELAPSED + CHECK_INTERVAL))


if [ "$ELAPSED" -ge "$GRACE_SEC" ]; then
CONTAINER_IDS=$(docker ps -q)
if [ -n "${CONTAINER_IDS}" ]; then
docker stop ${CONTAINER_IDS}
fi


exit 0
fi
fi
sleep $CHECK_INTERVAL
done

赋予脚本执行权限:chmod +x ~/.gpu_cleanup_daemon.sh

步骤二:配置终端环境与快捷指令

~/.bashrc 尾部添加以下配置。除了静默启动守护进程外,还封装了开关指令供日常调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17





export GPU_CLEANUP_GRACE_PERIOD="10m"


alias gpu-keep-on="touch ~/.skip_gpu_cleanup && echo -e '\033[32m[Long-run Mode Enabled]\033[0m Your Docker containers will NOT be stopped upon disconnection.'"
alias gpu-keep-off="rm -f ~/.skip_gpu_cleanup && echo -e '\033[33m[Auto-Cleanup Mode Restored]\033[0m Your Docker containers will be automatically stopped after disconnection.'"
alias gpu-status="[ -f ~/.skip_gpu_cleanup ] && echo 'Current Mode: Long-running task (No cleanup)' || echo 'Current Mode: Auto-cleanup'"


if ! pgrep -u "${USER}" -f "gpu_cleanup_daemon.sh" > /dev/null; then
nohup bash ~/.gpu_cleanup_daemon.sh > /dev/null 2>&1 &
disown
fi

执行 source ~/.bashrc 使配置生效。


5. 总结与实践建议

  1. 实际资源释放延迟:由于 Ubuntu 默认依赖底层的 TCP 机制判断异常断线,实际的容器停止时间等于 TCP 释放延迟(约 15~30 分钟)+ 脚本缓冲时间(10 分钟)。这种物理延迟恰好提供了业务上的双重缓冲冗余。
  2. 数据安全性:采用 Rootless Docker 环境时,执行 docker ps -q 只能获取当前用户空间下的容器,因此直接进行 docker stop 操作是安全的,不存在误操作其他用户资源的风险。
  3. 资源占用极低:Bash 守护进程配合 10 秒级别的 sleep 轮询,对系统资源的消耗几乎为零。且完成清理任务后进程会自我销毁,避免了僵尸进程的累积。