![如果我使用绑定卷挂载删除我的 SQLite 数据库,为什么 Docker 不会抛出错误?](https://linux22.com/image/793234/%E5%A6%82%E6%9E%9C%E6%88%91%E4%BD%BF%E7%94%A8%E7%BB%91%E5%AE%9A%E5%8D%B7%E6%8C%82%E8%BD%BD%E5%88%A0%E9%99%A4%E6%88%91%E7%9A%84%20SQLite%20%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%20Docker%20%E4%B8%8D%E4%BC%9A%E6%8A%9B%E5%87%BA%E9%94%99%E8%AF%AF%EF%BC%9F.png)
所以我有使用 Next.js + SQLite + Litestream (Cloudflare R2 上的数据库备份) + Docker 的项目&我尝试对/data
容器上的文件夹(./data/
在磁盘上)执行数据库删除,以查看数据库是否正确恢复。
数据确实恢复正常。
rm -rf data/
但我很好奇,当我使用命令行删除数据库时。
它不会在我的应用程序中引发任何错误并且它继续工作。
即使在我删除了data/
文件夹之后,,,Add One
仍可继续工作。我不知道Get All
存储在哪里。Delete All
data/
Fwiw,我在 Docker Compose 中使用匿名卷绑定挂载。
docker-compose.yml
version: '3.8'
services:
web:
image: easypanel-nextjs:0.0.1
build:
context: .
dockerfile: Dockerfile
container_name: nextjs-sqlite
env_file:
- .env.production
ports:
- 3000:3000
volumes:
- ./data:/data
现在发生的情况是,数据只在我停止使用服务器后才有效docker-compose down
,然后当我再次重新启动时,它会回到之前的状态(在我执行之前rm -rf data
)
简而言之,
- 我愿意
docker-compose up
- 添加、获取、删除都可以。假设
data = { name: 'abby' }
data/
Litestream在每次插入或删除时都会进行备份。- 我删除了
data/
文件夹。 - 尽管
data/
包含我的文件夹*.sqlite
不存在,我仍然可以成功访问我的 Web 应用程序。它应该会在这里崩溃,但事实并非如此。 - 我仍然可以添加、获取、删除。假设我这样做
data = { name: 'abby', name: 'nia' }
- 现在,当我停止使用
docker-compose down
并再次运行它时docker-compose up
,我只得到data = { name = 'abby' }
。nia
被删除,因为我data/
在添加之前删除了文件夹nia
。
这是怎么回事?是使用匿名卷吗?无论我怎么尝试,我都无法进入匿名文件夹。如果我以某种方式访问匿名文件夹,我也不知道如何*.sqlite
在其中下载,以便查看其内容。
这种行为正常吗?我很想解决这个问题。比如,如果数据库不存在,它就会崩溃。
完整复制品可参见https://github.com/deadcoder0904/easypanel-nextjs-sqlite/
答案1
unlink() 从文件系统中删除一个名称。如果该名称是文件的最后一个链接,并且没有进程打开该文件,则该文件将被删除,并且它所占用的空间可供重新使用。
如果名称是文件的最后一个链接,但任何进程仍打开该文件,则该文件将一直存在,直到引用它的最后一个文件描述符被关闭
答案2
作为亚历克斯评论中说,它不会删除文件。
它只是删除了对它的引用。就像 C 中的指针一样。
因此该文件仍然存在并且所有数据库操作仍在进行。
一旦文件关闭,它实际上就被删除了。
如果您在 Docker 中使用 Windows(主机)和 Linux(容器),这会非常令人困惑。
因为在 Windows 中你可以看到目录被删除了。在 Linux 中,如果你使用./data
检查,它也会被删除。/data
ls /data
我这样做了并发现了这一点:
$ docker exec -it nextjs-sqlite sh
/app $ ls /data
ls: /data: No such file or directory
但我猜它并没有真正被删除。也许这就是Linux 工作原理。 或许Windows 也是如此。