--restart=unless-stopped是容器自动恢复的硬性要求:宿主机重启、DSM升级或断电后,仅此策略能确保容器自动拉起;漏配则服务彻底中断,且不可用always替代,因其会掩盖启动失败。

--restart=unless-stopped 是硬性要求,不加它就不是自动化,只是临时能跑。
容器必须用 --restart=unless-stopped 启动
群晖NAS重启、DSM升级、断电恢复后,没加这个参数的容器不会自动拉起,脚本彻底失联——这不是“偶尔失效”,而是“一断就死”。
常见错误是只写 -d 或干脆漏掉 --restart:
• docker run -d python:3.11-slim python job.py → NAS重启后容器消失
• 正确写法必须包含 --restart=unless-stopped,且不能用 always(会掩盖启动失败)
• 如果用 docker-compose.yml,对应字段是 restart: unless-stopped
• 验证方式:执行 docker inspect mytask | grep -i restart,输出应含 "unless-stopped"
别用 docker run -it,也别用 docker exec -it 调脚本
交互式启动(-it)绑定终端 stdin/stdout,SSH断开或网页终端关闭,容器立刻退出;docker exec -it 在非交互环境(如DSM任务计划)里会卡住,截至2026年6月仍无可靠 workaround。
正确做法:
• 启动时去掉 -it,只留 -d
• 定时任务交给容器内守护进程,比如 supercronic(轻量、无依赖、支持 crontab 语法)
• 简单轮询可用 while true; do python job.py; sleep 3600; done,但要加 || true 防止某次失败导致整个循环退出
• DSM 的“用户定义脚本”只能作为触发器(例如发个 docker kill -s SIGUSR1 mytask),不能直接调 python
-v 和 -w 必须配对,否则 open("config.json") 直接报错
脚本里用相对路径读配置,却忘了容器内路径和宿主机不一致,是最常见的 FileNotFoundError 根源。
关键点:
• -v /volume1/docker/mytask:/app 把 NAS 上目录挂进容器
• -w /app 显式设工作目录,让 python job.py 的当前路径就是 /app
• 所有文件(job.py、config.json、logs/、output/)都放在这同一个挂载点下
• 别在容器里写 cd /volume1/scripts && python x.py —— 容器根本没有 /volume1/scripts 这个路径
• 挂载后检查:进入容器执行 ls -l /app,确认能看到你的脚本和配置文件
镜像选 python:3.11-slim,别碰 latest 或模糊标签
python:3 这类模糊标签会随 Docker Hub 自动更新,2026年5月起已出现多起因 zoneinfo 或 httpx 版本突变导致脚本崩溃的案例;latest 更被官方标记为“不推荐用于生产”。
稳妥选择:
• python:3.11-slim:固定小版本、基础层更小、启动更快、不含 gcc/make(纯 Python 脚本完全够用)
• 若真需编译依赖(如 pydantic-core),改用 python:3.11-bookworm 并在 Dockerfile 中显式装 build-essential
• 避免 python:3.12(部分库尚未兼容)、python:3.14.3(VS Code 扩展名,非运行时镜像)
立即学习“Python免费学习笔记(深入)”;
挂载点权限、时区、日志落盘这些细节,不显式声明就容易在某次 DSM 升级后突然出问题。自动化不是“一次跑通”,而是“三年不碰还能稳住”。


















