背景
uptime-kuma 当初是用 docker run 手起的,命令大概长这样:
docker run -d --restart=always \ -p 3001:3001 \ -v uptime-kuma:/app/data \ --name uptime-kuma \ louislam/uptime-kuma:1问题:不在 compose 里,服务器重启后要手动管;配置改动没有版本记录;端口暴露公网。
想迁移到 compose,但数据不能丢(里面有告警规则、监控目标、历史记录)。
原因
关键概念:Docker 卷是独立的。
docker run 时创建的卷叫 uptime-kuma
如果直接用 compose 定义同名卷,compose 会自动加项目前缀,变成 xxx_uptime-kuma(新卷)
新容器读新卷,看不到老数据
正确做法:在 compose 里声明 external: true,告诉 compose"用现有的卷,别新建"。
解决
第一步:备份数据(保命)
mkdir -p ~/backups/uptime-kuma docker run --rm \ -v uptime-kuma:/data \ -v /home/YOUR_USER/backups/uptime-kuma:/backup \ alpine \ tar czf /backup/uptime-kuma-$(date +%F).tar.gz -C /data . # 验证备份里有 kuma.db tar tzf ~/backups/uptime-kuma/*.tar.gz | grep kuma.db看到 kuma.db 才算备份成功。
第二步:写 compose 文件
services: uptime-kuma: image: louislam/uptime-kuma:1 container_name: uptime-kuma restart: always ports: - "127.0.0.1:3001:3001" # 撤下公网 volumes: - uptime-kuma:/app/data environment: - TZ=Asia/Shanghai mem_limit: 256m logging: driver: "json-file" options: max-size: "10m" max-file: "3" volumes: uptime-kuma: external: true # 🚨 关键!用现有卷,不新建external: true 是这一篇的核心。
第三步:验证 compose 解析结果
dockercompose config|grep-A2"volumes:"volumes: uptime-kuma: name: uptime-kuma ← 必须是 uptime-kuma如果看到 name: uptime-kuma_uptime-kuma → 🚨 停下,external: true 没生效,会新建卷、丢数据。
第四步:迁移(1 分钟窗口)
# 停 + 删旧容器(不加 -v!)dockerstop uptime-kumadockerrmuptime-kuma# 确认卷还在dockervolumels|grepuptimedockervolume inspect uptime-kuma|grepMountpoint# 用 compose 起新容器cd/home/YOUR_USER/uptime-kumadockercompose up-d⚠️ docker rm 千万不要加 -v——加了会连卷一起删。
第五步:验证数据完整
dockerlogs uptime-kuma2>&1|grep-E"Connected|Listening"|tail-5[SERVER] INFO: Connected [SERVER] INFO: Listening on 3001Connected = 成功读到老数据。浏览器登进去,监控目标、通知配置、历史记录都在。
三个坑
坑 1:忘了 external: true
compose 默认会给卷加项目前缀。docker run 建的 uptime-kuma 卷,到 compose 里会变成 项目名_uptime-kuma——新卷、空的、数据全丢。
坑 2:docker rm 加了 -v
docker rm uptime-kuma 删容器,卷保留。
docker rm -v uptime-kuma 删容器 + 删卷——数据全没。
迁移时永远不加 -v。
坑 3:迁移前后没验证 kuma.db
迁移前 tar 备份里要有 kuma.db,迁移后容器日志里要有 Connected。前后两头都验证,才能保证数据没丢。
外加推荐一部电影:挽救计划
昨天看完的,个人感觉——好看