持久化数据库
如果你没注意到,每次启动容器时,你的待办事项列表都是空的。这是为什么?在本部分中,你将深入了解容器是如何工作的。
容器的文件系统
容器运行时,其文件系统使用来自镜像的各种分层。每个容器还会获得自己的“暂存空间”来创建/更新/删除文件。任何更改在其他容器中都不可见,即使它们使用相同的镜像也是如此。
实际演示
为了实际演示这一点,你将启动两个容器。在一个容器中,你将创建一个文件。在另一个容器中,你将检查该文件是否存在。
启动一个 Alpine 容器并在其中创建一个新文件。
$ docker run --rm alpine touch greeting.txt
提示
在镜像名称(本例中为
alpine
)后指定的任何命令都在容器内部执行。在本例中,命令touch greeting.txt
在容器的文件系统上放置了一个名为greeting.txt
的文件。运行一个新的 Alpine 容器,并使用
stat
命令检查文件是否存在。$ docker run --rm alpine stat greeting.txt
你应该会看到类似以下的输出,表明该文件在新容器中不存在。
stat: can't stat 'greeting.txt': No such file or directory
第一个容器创建的 greeting.txt
文件在第二个容器中不存在。这是因为每个容器的可写“顶层”是相互隔离的。即使两个容器共享构成基础镜像的相同底层,可写层对于每个容器来说也是唯一的。
容器卷
通过之前的实验,你看到每个容器每次启动时都从镜像定义开始。虽然容器可以创建、更新和删除文件,但当你删除容器时,这些更改会丢失,而且 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
,这将捕获在该路径下创建的所有文件。$ docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started
注意
如果你使用的是 Git Bash,则必须为此命令使用不同的语法。
$ docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=//etc/todos getting-started
有关 Git Bash 语法差异的更多详细信息,请参阅使用 Git Bash。
创建卷
- 在 Docker Desktop 中选择 卷。
- 在 卷 中,选择 创建。
- 将
todo-db
指定为卷名称,然后选择 创建。
停止并删除应用容器
- 在 Docker Desktop 中选择 容器。
- 在容器的 操作 列中选择 删除。
启动挂载卷的待办事项应用容器
选择 Docker Desktop 顶部的搜索框。
在搜索窗口中,选择 镜像 选项卡。
在搜索框中,指定镜像名称
getting-started
。提示
使用搜索过滤器筛选镜像,仅显示 本地镜像。
选择你的镜像,然后选择 运行。
选择 可选设置。
在 宿主机端口 中,指定端口,例如
3000
。在 宿主机路径 中,指定卷的名称,
todo-db
。在 容器路径 中,指定
/etc/todos
。选择 运行。
验证数据是否持久化
容器启动后,打开应用并添加一些事项到你的待办事项列表中。
停止并删除待办事项应用容器。使用 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 权限才能从宿主机访问此目录。
总结
在本章节中,你学习了如何持久化容器数据。
相关信息
下一步
接下来,你将学习如何使用绑定挂载更高效地开发应用。