Docker记录:误删宿主机挂载目录导致 PostgreSQL 数据丢失

发布时间:2026/9/6 15:45:21
Docker记录:误删宿主机挂载目录导致 PostgreSQL 数据丢失 Docker记录误删宿主机挂载目录导致 PostgreSQL 数据丢失1. Docker启动PostgreSQL服务2. 我删了什么3. Ooops问题来了4.问题核心为什么删掉宿主机目录后容器数据就访问不了5.总结最近在使用 Docker 部署 PostgreSQL 时踩了一个坑因为对 -v 参数理解不够深入误删了宿主机上的挂载目录结果容器内的数据“凭空消失”了。这个过程中还存在其他操作错误这篇博客记录一下这个问题的来龙去脉希望能帮助其他朋友避开同样的坑。1. Docker启动PostgreSQL服务我的项目分为一期和二期代码文件夹名暂且叫做period1和period2。一期开发的时候我用docker启动postgreSQL服务。代码目录在/home/root/period1/sudodockerrun-d\--namedb_ai\-ePOSTGRES_PASSWORD123456\-ePOSTGRES_DBdb1\-ePOSTGRES_USERpostgre_db\-v/home/root/period1/postgres_data:/var/lib/postgresql\-p5432:5432\postgres:latest命令本身没问题服务也正常启动。我在这个postgres docker容器中建立了一期的数据表。二期开发的时候我建了period2文件夹来存二期的代码使其不影响一期服务。代码目录在/home/root/period2。并且我在docker中另建了一张二期的数据表将数据在软件层面隔离。并且认为只要我不删这个docker容器数据就会妥妥的一直在里面。2. 我删了什么二期顺利上线了该清清一期的旧数据了。我做了两件事我进入postgres docker容器将Period1 data表删除我将一期的代码删除代码目录在/home/root/period1/3. Ooops问题来了我用rm -rf删掉了一期整个代码目录/home/root/period1然后悲剧发生了二期的代码服务中postgres数据库无法正常使用查postgres docker状态已经自动退出。我想着退出就退出吧重启一下服务就行了。结果发现重启后之前没删的二期数据库、表都不存在了回到上一节我删了什么第1删表不会有问题那问题就出现在2删了代码目录。我使用的docker启动postgreSQL服务的命令中-v /宿主机路径:/var/lib/postgresql实际上是将docker容器内路径映射到宿主机路径中数据实际存储在宿主机目录/home/root/period1/postgres_data中二期使用的同一个docker相当于二期的数据也在这个目录中。当我执行rm -rf删除/home/root/period1等于直接删了数据库的所有物理文件表数据、索引、事务日志等。当我重启容器后容器发现找不到/home/root/period1/postgres_data会自动执行initdb初始化一个新的空白数据库实例。赶紧尝试恢复文件时间一分一秒过去要知道当我删了这个目录相当于计算机中的一块内存被释放那么其他服务、日志在磁盘的写入都有可能会覆盖这块内存就无力回天了。AI告诉我赶紧卸载这块分区阻止任何新的写入操作避免已删除的数据块被覆盖但问题又出现了卸载分区失败。WHY?/home/root/并不是独立的数据分区而是系统根分区意味着系统本身在不断写入日志、临时文件等导致卸载失败。如果我在这个分区上直接强行运行恢复工具可能导致系统崩溃。遂放弃恢复只能重传数据。4.问题核心为什么删掉宿主机目录后容器数据就访问不了这又要讲到docker的挂载方式我使用的是Bind Mount挂载方式容器不保存数据的副本类比把一个U盘宿主机目录插在电脑上docker容器。电脑里的文件数据库数据实际存储在U盘上我把U盘拔掉并格式化rm -rf电脑里的“文件快捷方式”还在但指向的物理储存已经没了所以电脑打不开这些文件。如果我当时用Docker volume或容器内部存储情况都会不一样。Docker volume挂载示例# 创建 volumesudodockervolume create postgres_data# 使用 volumesudodockerrun-d\--namepostgres_ai\-ePOSTGRES_PASSWORD123456\-ePOSTGRES_DBai\-vpostgres_data:/var/lib/postgresql/data\-p5432:5432\postgres:latestDocker内部挂载示例sudodockerrun-d\--namepostgres_ai\-ePOSTGRES_PASSWORD123456\-ePOSTGRES_DBai\-p5432:5432\postgres:latest但Docker内部挂载的话如果把容器删了数据也会丢不推荐。5.总结Bind Mount是共享而非复制删了宿主机目录容器虽然活着但数据没了。数据相关的文件不要放在项目代码中并需要设独立分区。这样即使误删了也有恢复的可能性。服务器上每个项目相关的文件夹都要备份确保备份数据和服务器上数据一致。