持久化到数据库
容器的文件系统
当一个容器运行的时候,他会使用镜像所来带的各种层作为自己的文件系统。每个容器也有属于自己的暂存空间来创建、更新、删除文件。
实践
在实践中,我们将启动两个容器,并单独地给他们创建一个文件。你将会看到一个容器中创建的文件不会在另一个容器中看到。
启动一个 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 后会执行两条命令。第一个是选取一个随机数写入到
/data.txt
中。第二条命令是用来实时查看这个文件,来让这个容器保持运行的状态之中。在 Dashboard 中点击容器对应的第一个行为,来查看容器的输出。
你将会看到一个该 ubuntu 容器的终端。执行下面的命令来查看
/data.txt
的内容。cat /data.txt
如果想用命令行来执行以上操作的话,可以使用
docker exec
命令。你需要容器的 ID (通过使用docker ps
获取)。docker exec <container-id> cat /data.txt
然后你应该会看到一个随机的数字。
接着,启动另一个 ubuntu 容器(使用同一个镜像),我们会发现容器中没有刚才的文件。
docker run -it ubuntu ls /
使用
docker rm -f
将第一个容器移除。
容器挂载卷 Container Volumes
从上面的实践中发现,容器中文件的变化是相对独立的,但我们可以使用挂载卷来避开这一属性。
挂载卷提供了容器中指定的文件系统与主机相连接的特性。如果一个目录在容器中被挂载了,那么目录中的变化在主机中也是可见的。如果我们挂载同一目录来重启容器,我们会在容器中看到相同的文件。
有两种挂载卷,首先我们使用命名挂载
持久化我们的待办数据
由于数据库是单个文件,如果我们能将这个文件保留在主机中并且能够在下一个容器中使用,则它应该知道上一次该文件放在那儿并获取它。通过创建一个挂载卷并挂载存储数据所在的目录,我们就能持久化数据。因为我们的容器在 todo.db
文件中写入,我们应当将它挂载在主机中。
我们将会使用命名挂载,docker 会保留磁盘中的物理路径,同时你只需记得挂载卷的名称即可。
- 创建一个挂载卷,通过使用
docker volume create
命令。docker volume create todo-db
- 在 Dashboard 中停止我们的待办应用容器(或者使用
docker rm -f <id>
)。 - 启动我们的待办应用,但这次我们加上
-v
修饰符来明确挂载一个卷。我们将使用一个命名卷来挂载到/etc/todos
中,这个路径会捕捉所有文件。docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
- 一旦容器运行了,我们打开应用然后在待办中添加一些事件。
- 移除该容器。使用 Dashboard ,或者是使用
docker ps
来获取容器 ID ,然后用docker rm -f <id>
来移除。 - 用刚才相同的命令来启动一个新的容器。
- 我们打开应用,发现事件仍然在待办列表中。
- 完成后就把容器移除吧。
尽管命名挂载和绑定挂载(稍后会讨论)是 Docker 提供的两种主要的挂载卷类型,但还有许多用来支持 NFS、SFTP、NetApp 等的挂载卷驱动插件可用。一旦开始在具有Swarm,Kubernetes等集群环境中的多个主机上运行容器,这将尤其重要。
深入了解挂载卷
如果你想知道命名挂载存放数据的实际位置,可以使用 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
就是我们实际的数据存储位置。
在 Docker Desktop 中运行时,Docker 命令实际上在计算机上的小型VM内运行。 如果要查看 Mountpoint 目录的实际内容,则需要首先进入 VM 。