如果我使用绑定卷挂载删除我的 SQLite 数据库,为什么 Docker 不会抛出错误?

如果我使用绑定卷挂载删除我的 SQLite 数据库,为什么 Docker 不会抛出错误?

所以我有使用 Next.js + SQLite + Litestream (Cloudflare R2 上的数据库备份) + Docker 的项目&我尝试对/data容器上的文件夹(./data/在磁盘上)执行数据库删除,以查看数据库是否正确恢复。

数据确实恢复正常。

rm -rf data/但我很好奇,当我使用命令行删除数据库时。

它不会在我的应用程序中引发任何错误并且它继续工作。

本地主机上的示例数据库

即使在我删除了data/文件夹之后,,,Add One仍可继续工作。我不知道Get All存储在哪里。Delete Alldata/

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

简而言之,

  1. 我愿意docker-compose up
  2. 添加、获取、删除都可以。假设data = { name: 'abby' }
  3. data/Litestream在每次插入或删除时都会进行备份。
  4. 我删除了data/文件夹。
  5. 尽管data/包含我的文件夹*.sqlite不存在,我仍然可以成功访问我的 Web 应用程序。它应该会在这里崩溃,但事实并非如此。
  6. 我仍然可以添加、获取、删除。假设我这样做data = { name: 'abby', name: 'nia' }
  7. 现在,当我停止使用docker-compose down并再次运行它时docker-compose up,我只得到data = { name = 'abby' }nia被删除,因为我data/在添加之前删除了文件夹nia

这是怎么回事?是使用匿名卷吗?无论我怎么尝试,我都无法进入匿名文件夹。如果我以某种方式访问​​匿名文件夹,我也不知道如何*.sqlite在其中下载,以便查看其内容。

这种行为正常吗?我很想解决这个问题。比如,如果数据库不存在,它就会崩溃。

完整复制品可参见https://github.com/deadcoder0904/easypanel-nextjs-sqlite/

答案1

引自unlink(2) 手册页

unlink() 从文件系统中删除一个名称。如果该名称是文件的最后一个链接,并且没有进程打开该文件,则该文件将被删除,并且它所占用的空间可供重新使用。

如果名称是文件的最后一个链接,但任何进程仍打开该文件,则该文件将一直存在,直到引用它的最后一个文件描述符被关闭

答案2

作为亚历克斯评论中说,它不会删除文件。

它只是删除了对它的引用。就像 C 中的指针一样。

因此该文件仍然存在并且所有数据库操作仍在进行。

一旦文件关闭,它实际上就被删除了。

如果您在 Docker 中使用 Windows(主机)和 Linux(容器),这会非常令人困惑。

因为在 Windows 中你可以看到目录被删除了。在 Linux 中,如果你使用./data检查,它也会被删除。/datals /data

我这样做了并发现了这一点:

$ docker exec -it nextjs-sqlite sh
/app $ ls /data
ls: /data: No such file or directory

但我猜它并没有真正被删除。也许这就是Linux 工作原理。 或许Windows 也是如此

相关内容