我再也不敢随手 `docker compose down -v` 了

这次复盘一个很典型的 Compose 维护事故。

一个小团队的内部工具用 Docker Compose 跑,里面有 apppostgresredisnginx。升级前大家习惯性执行:

bash 复制代码
docker compose pull
docker compose up -d

结果应用起来了,数据库却像新装的一样。排查到最后,不是 Postgres 镜像坏了,也不是应用迁移脚本漏跑,而是数据卷管理一直很随意:旧环境有匿名卷,新环境项目名变了;另一次清理环境时还执行过 docker compose down -v

这篇按工程复盘写,重点是 Compose 数据卷、数据库备份和恢复验证。

先看最终配置

维护前第一条命令不是 pull,而是:

bash 复制代码
docker compose config

我主要看三块:

  • 数据库服务的 volumes
  • image 是否固定 tag。
  • 环境变量里数据库名、用户、密码是否清楚。

一个更稳的 Postgres 写法:

yaml 复制代码
services:
  db:
    image: docker.1ms.run/postgres:16
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: change-me
      POSTGRES_DB: app
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

不一定所有项目都要这么写,但数据库目录不能飘在匿名卷里,至少要知道数据卷叫什么。

down 不等于删数据,down -v 才危险

这个误区很常见。

docker compose down 默认不会删除命名卷。真正要小心的是:

bash 复制代码
docker compose down -v

它会把 Compose 文件里声明的命名卷和容器使用的匿名卷一起移除。对无状态服务来说,这可能只是清理;对数据库来说,这就是销毁状态。

匿名卷更麻烦。它默认不会被删,但名字不稳定。项目目录、项目名、服务定义变了以后,新环境可能直接生成新卷,你还以为数据库初始化失败。

我现在升级前固定查这几条

列卷:

bash 复制代码
docker volume ls

查卷详情:

bash 复制代码
docker volume inspect 项目名_db-data

查容器实际挂载:

bash 复制代码
docker inspect 容器名 --format '{{json .Mounts}}'

这三条能回答一个问题:数据库到底在写哪里?

如果这个问题答不上来,后面不要升级。

备份要能恢复

只说"我有备份"没用。备份必须在临时环境里恢复一次。

MySQL:

bash 复制代码
docker compose exec db sh -c 'mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" app' > mysql-app.sql
cat mysql-app.sql | docker compose exec -T db sh -c 'mysql -uroot -p"$MYSQL_ROOT_PASSWORD" app'

Postgres:

bash 复制代码
docker compose exec -T db pg_dump -U app app > pg-app.sql
cat pg-app.sql | docker compose exec -T db psql -U app app

Postgres 跨大版本时还要看 PGDATA 和数据目录说明,不要把旧路径习惯直接套到新镜像上。

Redis 不一定只是缓存

Redis 容器最容易被一句"缓存丢了没事"带过去。

但实际项目里,Redis 可能放了:

  • 登录会话。
  • 任务队列。
  • 限流状态。
  • 延迟任务。
  • 临时业务状态。

如果这些状态对业务有影响,就要明确持久化:

yaml 复制代码
services:
  redis:
    image: docker.1ms.run/redis:7
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redis-data:/data

volumes:
  redis-data:

同时不要把无密码 Redis 暴露到公网。

镜像预检不是第一步

升级前我会预拉镜像,但它不是第一步。我的顺序现在固定成:

text 复制代码
查配置 -> 查卷 -> 备份 -> 恢复演练 -> 预拉镜像 -> 升级 -> 验证

镜像预检这一步可以这样做:

bash 复制代码
docker pull docker.1ms.run/postgres:16
docker pull docker.1ms.run/mysql:8.4
docker pull docker.1ms.run/redis:7
docker pull docker.1ms.run/adminer:latest

这里用 docker.1ms.run 只是为了把镜像拉取这层提前排掉。镜像拉得下来,不代表数据安全;但镜像拉不下来,维护窗口也会被拖住。

复盘清单

问题 检查方式
数据在哪个卷里 docker volume inspect
Compose 最终配置是什么 docker compose config
有没有匿名卷 docker volume ls + docker inspect
down -v 会不会误删 看脚本和维护手册
MySQL/Postgres 能否恢复 临时环境导入一次
Redis 是否需要状态 看业务是否依赖持久化
镜像是否可拉 固定 tag 预拉

这次之后,我对 Compose 有状态服务的态度很简单:容器重建是日常操作,数据恢复必须提前证明。

相关推荐
程序员小羊!1 小时前
集团多事业部架构下数仓分层建模规范
架构
ARM|X86+FPGA工业主板厂家3 小时前
RK3588+FPGA+EtherCAT异构架构解析|工业场景如何同时保住AI算力与微秒级运动实时性
人工智能·fpga开发·架构
小码哥哥3 小时前
四大企业AI知识库技术架构深度对比:从设计哲学到实现差异
人工智能·架构
2601_9605679610 小时前
电商套图批处理架构的性能分析——逐图生成与流水线模式的工程对比
架构
老刘说AI11 小时前
SGLang 深度优化: Radix 缓存与复杂任务的极致吞吐
人工智能·神经网络·机器学习·缓存·架构·sglang
Georgeviewer11 小时前
实体门店SaaS系统适配困境深度解析:通用模板架构为何无法支撑线下商业落地
架构
●VON11 小时前
鸿蒙 PC Markdown 编辑器通信架构:受限 ArkTS-JavaScript Bridge
华为·架构·编辑器·harmonyos·鸿蒙
chaoxiaomai11 小时前
电商套图批处理架构的性能分析——逐图生成与流水线模式的工程对比
架构
沸速存储11 小时前
内存技术的未来:DDR6、CAMM2与CXL将如何改变计算架构
科技·嵌入式硬件·架构·计算机外设·电脑
人间凡尔赛11 小时前
K8s 十年之变:从 Cloud Native 到 AI Native,2026 年后端架构的范式革命
后端·云原生·架构