Docker将DB持久化
如果你没有注意到的话,每次启动容器时你的待办事项列表都是空的。为什么会这样呢?在这部分,你将深入了解容器的工作原理。
容器的文件系统
当容器运行时,它使用来自镜像的各个层级来构建自己的文件系统。每个容器还会有自己的”临时空间”用于创建/更新/删除文件。任何更改都不会在其他容器中可见,即使它们使用的是同一个镜像。
实际操作中的示例
为了看到这个过程,你将启动两个容器并在每个容器中创建一个文件。你会发现,一个容器中创建的文件在另一个容器中是不可用的。
注意事项
如果你使用的是Windows并且想要使用Git Bash运行Docker命令,请参考与语法差异相关的Git Bash使用指南。
- 启动一个ubuntu容器,该容器将创建一个名为/data.txt的文件,并在其中写入1到10000之间的一个随机数。
docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
如果你对这个命令感兴趣,你正在启动一个bash shell并调用两个命令(为什么需要&&)。第一部分选择一个随机数并将其写入/data.txt。第二个命令只是监视文件以保持容器运行。
- 验证你是否可以通过访问容器中的终端来看到输出。你可以使用CLI或者Docker Desktop的图形界面来实现。
在命令行中,使用docker exec命令来访问容器。你需要获取容器的ID(使用docker ps来获取)。在Mac或Linux终端,或者Windows的Command Prompt或PowerShell中,使用以下命令来获取内容。
docker exec <container-id> cat /data.txt
你应该能够看到一个随机数。
- 现在,启动另一个ubuntu容器(相同的镜像),你会发现你没有相同的文件。在Mac或Linux终端,或Windows的Command Prompt或PowerShell中,使用以下命令获取内容。
docker run -it ubuntu ls /
在这种情况下,该命令列出了容器根目录中的文件。看,那里没有data.txt文件!那是因为它只被写入了第一个容器的临时空间。
- 接下来,使用docker rm -f <container-id>命令删除第一个容器。
容器卷
通过上面的实验,你可以看到每次启动容器时,它都是从镜像定义开始的。虽然容器可以创建、更新和删除文件,但当你删除容器时,这些更改都会丢失,Docker将所有更改隔离到该容器中。通过使用卷,你可以改变这一切。
卷提供了将容器的特定文件系统路径连接到主机机器的能力。如果你将容器中的一个目录挂载到主机机器上,那么该目录中的更改也会在主机机器上可见。如果你在多个容器重启时挂载相同的目录,你将看到相同的文件。
卷有两种主要类型。你最终会同时使用这两种,但首先你将使用卷挂载。
持久化待办事项数据
默认情况下,待办事项应用程序将其数据存储在容器文件系统中的/etc/todos/todo.db SQLite数据库中。如果你不熟悉SQLite,不用担心!它只是一个关系型数据库,将所有数据存储在一个单独的文件中。虽然这对于大规模应用程序来说并不是最好的选择,但它适用于小型演示。你将在后面学习如何切换到不同的数据库引擎。
由于数据库是一个单独的文件,如果你可以将该文件持久化到主机上,并在下一个容器中使其可用,那么容器就能够从上一个容器停止的地方继续执行。通过创建一个卷并将其附加(通常称为“挂载”)到存储数据的目录,你可以持久化数据。当容器向todo.db文件写入数据时,它将通过卷将数据持久化到主机上。
正如前面提到的,你将使用卷挂载。将卷挂载视为一个不透明的数据桶。Docker完全管理卷,包括磁盘上的存储位置。你只需要记住卷的名称即可。
创建一个卷并启动容器
你可以使用CLI或Docker Desktop的图形界面来创建卷并启动容器。
- 使用docker volume create命令创建一个卷。
docker volume create todo-db
使用docker rm -f <id>停止并删除待办事项应用程序容器,因为它仍在运行且没有使用持久化卷。
启动待办事项应用程序容器,但添加–mount选项来指定卷挂载。给卷一个名称,并将其挂载到容器中的/etc/todos目录,以捕获在该路径下创建的所有文件。在Mac或Linux终端,或Windows的Command Prompt或PowerShell中,运行以下命令:
docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
验证数据是否持久化 容器启动后,打开应用程序并向待办事项列表中添加几个项目。
停止并删除待办事项应用程序的容器。使用Docker Desktop或docker ps命令获取ID,然后使用docker rm -f <id>命令将其删除。
使用上述步骤启动一个新的容器。
打开应用程序。你应该能够看到你的项目仍然在列表中。
完成查看列表后,可以删除容器。
现在你已经学会了如何持久化数据。
深入了解卷
很多人经常问:“当我使用卷时,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访问权限才能从主机访问该目录。