坚持数据库

预计阅读时间:7分钟

如果您没有注意到,每次启动容器时,我们的待办事项清单都会被清除干净。为什么是这样?让我们深入研究一下容器的工作方式。

容器的文件系统

容器运行时,它将映像中的各个层用于其文件系统。每个容器还拥有自己的“暂存空间”以创建/更新/删除文件。即使使用相同的图像,不会在其他容器中看到任何更改。

在实践中看到这一点

为了了解这一点,我们将启动两个容器,并在每个容器中创建一个文件。您会看到,在一个容器中创建的文件在另一个容器中不可用。

  1. 启动一个ubuntu容器,该容器将创建一个名称为/data.txt1到10000之间的随机数的文件。

     docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
    

    如果您对命令感到好奇,我们将启动一个bash shell并调用两个命令(为什么要使用&&)。第一部分选择一个随机数并将其写入/data.txt。第二个命令只是监视文件以保持容器运行。

  2. 验证我们可以exec通过进入容器来查看输出。为此,请打开仪表板,然后单击运行ubuntu图像的容器的第一个动作。

    仪表板打开CLI进入ubuntu容器

    您将在ubuntu容器中看到一个正在运行Shell的终端。运行以下命令以查看/data.txt文件的内容。然后再次关闭此终端。

     cat /data.txt
    

    如果您更喜欢命令行,则可以使用该docker exec命令执行相同的操作。您需要获取容器的ID(用于docker ps获取它),并使用以下命令获取内容。

     docker exec <container-id> cat /data.txt
    

    您应该会看到一个随机数!

  3. 现在,让我们启动另一个ubuntu容器(相同的图像),我们将看到我们没有相同的文件。

     docker run -it ubuntu ls /
    

    看!那里没有data.txt文件!那是因为它仅被写入第一个容器的暂存空间。

  4. 继续并使用docker rm -f命令删除第一个容器。

货柜量

在之前的实验中,我们看到每个容器每次启动时都从图像定义开始。尽管容器可以创建,更新和删除文件,但是当删除容器并将所有更改隔离到该容器时,这些更改将丢失。有了卷,我们可以改变所有这些。

提供了将容器的特定文件系统路径连接回主机的功能。如果装入了容器中的目录,则在主机上也会看到该目录中的更改。如果在重新启动容器时安装相同的目录,则会看到相同的文件。

卷有两种主要类型。最终,我们将同时使用这两种方法,但将从命名卷开始。

保留待办事项数据

默认情况下,todo应用程序将其数据存储在SQLite数据库/etc/todos/todo.db。如果您不熟悉SQLite,请不用担心!它只是一个关系数据库,其中所有数据都存储在一个文件中。虽然这对于大型应用程序不是最佳选择,但适用于小型演示。稍后我们将讨论将其切换到其他数据库引擎。

由于数据库是单个文件,因此如果我们可以将该文件持久保存在主机上并使其可用于下一个容器,则它应该能够从上一个中断的位置继续。通过创建一个卷并将其附加(通常称为“安装”)到存储数据的目录,我们可以持久保存数据。当我们的容器写入todo.db文件时,它将被持久化到卷中的主机上。

如前所述,我们将使用命名卷。可以将命名卷视为简单的数据桶。Docker维护磁盘上的物理位置,您只需要记住卷的名称即可。每次使用该卷时,Docker将确保提供正确的数据。

  1. 使用docker volume create命令创建一个卷。

     docker volume create todo-db
    
  2. 停止并在仪表板中(或通过docker rm -f <id>)再次删除待办事项应用程序容器,因为它仍在运行,而无需使用持久卷。

  3. 启动todo应用程序容器,但添加-v标志以指定卷安装。我们将使用命名的卷并将其安装到/etc/todos,它将捕获在路径中创建的所有文件。

     docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
    
  4. 容器启动后,打开应用程序并将一些项目添加到您的待办事项列表中。

    已添加到待办事项列表中的项目

  5. 停止并删除待办事项应用程序的容器。使用控制板或docker ps获取ID,然后docker rm -f <id>将其删除。

  6. 从上方使用相同的命令启动新容器。

  7. 开启应用程式。您应该会在列表中看到您的物品!

  8. 完成清单核对后,继续删除容器。

万岁!您现在已经学会了如何持久存储数据!

笔记

虽然命名卷和绑定挂载(我们将在稍后讨论)是默认Docker引擎安装支持的两种主要卷类型,但是有许多可用的卷驱动程序插件来支持NFS,SFTP,NetApp等!一旦开始在具有Swarm,Kubernetes等集群环境中的多个主机上运行容器,这将特别重要。

潜入音量

很多人经常问:“当我使用命名卷时,Docker实际上将数据存储在哪里?” 如果您想知道,可以使用docker volume inspect命令。

docker volume inspect todo-db
[
    {
        "CreatedAt": "2019-09-26T02:18:36Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
        "Name": "todo-db",
        "Options": {},
        "Scope": "local"
    }
]

Mountpoint是数据存储在磁盘上的实际位置。请注意,在大多数计算机上,您将需要具有root用户访问权限才能从主机访问此目录。但是,就是那里!

直接在Docker Desktop上访问卷数据

在Docker Desktop中运行时,Docker命令实际上在计算机上的小型VM中运行。如果要查看Mountpoint目录的实际内容,则需要首先进入VM。

回顾

至此,我们有了一个可以正常运行的应用程序,可以在重启后继续运行!我们可以向投资者展示它,并希望他们能抓住我们的眼光!

但是,我们较早时看到,为每次更改重建图像都需要花费大量时间。必须有一种更好的方式进行更改,对不对?使用bind mounts(我们在前面已经暗示过),有更好的方法!让我们现在来看一下!

入门设置方向快速启动简介概念容器码头