docker持久化
1.容器的文件系统
当容器运行时,它所使用的镜像中的各个层作为其文件系统,每个容器还有自己的"暂存空间"来创建,更新,删除文件.在使用相同镜像的另一个容器中不会看到任何更改.
为了查看这个操作,我们将启动两个容器,并在每个容器中创建一个文件。您将看到在一个容器中创建的文件在另一个容器中不可用。
启动一个 ubuntu 容器,该容器将创建一个名为/data.txt 的文件,该文件的随机数在1到10000之间。
docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
进入容器通过shell终端查看data.txt文件内容,之后关闭这个终端
cat data.txt
也可以通过docker命令来查看容器内的文件内容
# 查看容器内文件
docker exec <container-id> cat /data.txt
启动相同镜像的另一个容器,发现没有内容,这是因为文件只写入了第一个文件的暂存空间
docker run -it ubuntu ls /
2.容器卷
在前面的案例中,我们看到每个容器在每次启动时都从镜像定义开始。虽然容器可以创建、更新和删除文件,但是当容器被删除时,这些更改将丢失,所有更改都与该容器隔离。通过卷,我们可以改变这一切。
卷提供了将容器的特定文件系统路径连接回主机的能力。如果挂载了容器中的一个目录,则该目录中的更改也可以在主机上看到。如果我们跨容器重新启动挂载相同的目录,我们将看到相同的文件。
有两种主要的卷类型,我们最终将同时使用它们,但是我们将从卷装入开始。
1.保持 todo 数据
默认情况下,todo 应用程序将其数据存储在容器的文件系统中的/etc/todos/todo.db 的 SQLite 数据库中。如果您不熟悉 SQLite,不用担心!它只是一个关系数据库,所有的数据都存储在一个文件中。虽然这不是最好的大型应用程序,但它适用于小型演示。稍后我们将讨论将其切换到另一个数据库引擎。
由于数据库是一个单独的文件,如果我们可以在主机上持久存储该文件并使其可用于下一个容器,那么它应该能够从上一个容器停止的地方继续。通过创建卷并将其附加(通常称为“挂载”)到存储数据的目录,我们可以持久化数据。当我们的容器写入 todo.db 文件时,它将被持久化到卷中的主机。
1.1正如前面提到的,我们将使用一个卷加载。可以将卷装入看作是一个不透明的数据桶。Docker 完全管理卷,包括卷存储在磁盘上的位置。您只需要记住卷的名称。
通过docker volume create
命令创建
docker volume create todo-db
1.2启动 todo app 容器,但是添加—— mount 选项来指定卷装入。我们将为卷命名,并将其挂载到容器中的/etc/todos,这将捕获在路径中创建的所有文件。
docker run -dp 3000:3000 --mount type=volume,src=todo-db,target=/etc/todos 1042798703/getting-started
1.3容器启动之后,打开应用程序,并添加一些项目到您的待办事项列表。
1.4 停止并删除 todo 应用程序的容器。使用 Dashboard 或 docker ps 获取 ID,然后 docker rm-f < ID > 删除它。
1.5 使用上面的相同命令启动一个新容器。
1.6 打开应用程序。您应该看到您的项目仍然在您的列表!
1.7检查完列表后,继续移除容器。
现在,已经学会了如何持久化数据
2.深入研究卷
很多人经常问“当我使用卷时,Docker 在哪里存储我的数据?”如果您想知道,可以使用 docker 卷检查命令。
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 是存储数据的磁盘上的实际位置。请注意,在大多数机器上,您需要有根访问权限才能从主机访问这个目录。但是,它就在那里!
3.使用绑定挂载
在上面,我们讨论并使用卷装载来保存数据库中的数据。当您需要在某个地方持久存储应用程序数据时,卷挂载是一个很好的选择。
绑定挂载是另一种类型的挂载,它允许您将一个目录从主机的文件系统共享到容器中。在处理应用程序时,可以使用绑定挂载将源代码挂载到容器中。一旦保存文件,容器就会立即看到您对代码所做的更改。这意味着您可以在容器中运行进程,以监视文件系统的更改并对其作出响应。
两种挂载的区别
卷挂载 Named volumes | 绑定挂载 Bind mounts | |
---|---|---|
主机位置 | docker选择 | 你来选择 |
挂载示例(使用—— Mount) | type=volume,src=my-volume,target=/usr/local/data``Type = volul,src = my-volul,target =/usr/local/data | type=bind,src=/path/to/data,target=/usr/local/data``Type = bind,src =/path/to/data,target =/usr/local/data |
用容器内容填充新卷 | Yes | No |
支持卷驱动程序 | Yes | No |
下面让我们使用下绑定挂载
在研究如何使用绑定挂载来开发我们的应用程序之前,让我们运行一个快速的实验来实际了解绑定挂载是如何工作的。
1.打开一个终端,确保你当前的工作目录位于开始存储库的 app 目录中
2.运行以下命令在带绑定挂载的 ubuntu 容器中启动 bash。
docker run -it --mount type=bind,src="$(pwd)",target=/src ubuntu bash
--mount
选项告诉 Docker 创建一个绑定挂载,其中 src 是主机上的当前工作目录(getting-start/app) ,target 是该目录应该出现在容器(/src)中的位置。
3.运行该命令后,Docker 在容器文件系统的根目录中启动一个交互式 bash 会话。
root@ac1237fad8db:/# pwd
/
root@ac1237fad8db:/# ls
bin dev home media opt root sbin srv tmp var
boot etc lib mnt proc run src sys usr
现在我们在容器/src中新增一个文件
root@ac1237fad8db:/src# touch myfile.txt
root@ac1237fad8db:/src# ls
Dockerfile myfile.txt node_modules package.json spec src yarn.lock
返回在宿主机可以看到
[root@VM-24-10-centos app]# ls
Dockerfile myfile.txt node_modules package.json spec src yarn.lock
[root@VM-24-10-centos app]#
4.从宿主机中删除 myfile.txt 文件。
5.进入容器查看文件,发现myflie.txt 文件也不存在了
root@ac1237fad8db:/src# ls
Dockerfile node_modules package.json spec src yarn.lock
3.1实际操作
1.下面的步骤说明如何运行具有绑定挂载的开发容器,该绑定挂载执行下列操作:
2.安装所有依赖项
3.启动 nodemon
来监视文件系统的更改
stop
掉所有1042798703/getting-started相关容器
在linux使用下面命令
docker run -dp 3000:3000 \
-w /app --mount type=bind,src="$(pwd)",target=/app \
node:18-alpine \
sh -c "yarn install && yarn run dev"
如果使用 Windows,请在 PowerShell 中使用以下命令。
docker run -dp 3000:3000 `
-w /app --mount type=bind,src="$(pwd)",target=/app `
node:18-alpine `
sh -c "yarn install && yarn run dev"
-
- dp 3000:3000-和之前一样。在分离(背景)模式下运行并创建一个端口映射
-
- w/app-设置命令运行的“工作目录”或工作目录
-
- mount type = bind,src = “ $(pwd)”,target =/app-bind 将工作目录从主机挂载到容器中的/app 目录中
-
Node: 18-alpine-要使用的镜像。注意,这是 Dockerfile 中我们应用程序的基础图像
您可以使用 docker 日志来查看日志,当您看到以下内容时,您将知道您已经准备好了:
docker logs -f <container-id>
nodemon src/index.js
[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] starting `node src/index.js`
Using sqlite database at /etc/todos/todo.db
Listening on port 3000
看完日志后,按 Ctrl + C 退出。
4.现在,更改应用程序。在 src/static/js/app.js 文件的第109行,将“ Add Item”按钮改为“ Add”:
- {submitting ? 'Adding...' : 'Add Item'}
+ {submitting ? 'Adding...' : 'Add'}
在浏览器中刷新页面,您应该会立即看到更改的反映。Node 服务器重新启动可能需要几秒钟。如果出现错误,请在几秒钟后尝试刷新。
你想做什么改变都可以。每次进行更改并保存文件时,noemon 进程都会自动重新启动容器中的应用程序。完成后,停止容器并使用以下方法构建新图像:
docker build -t getting-started .
刷新页面,您应该会立即看到更改的反映。Node 服务器重新启动可能需要几秒钟。如果出现错误,请在几秒钟后尝试刷新。
[外链图片转存中…(img-37t6ONR2-1676526270202)]
你想做什么改变都可以。每次进行更改并保存文件时,noemon 进程都会自动重新启动容器中的应用程序。完成后,停止容器并使用以下方法构建新图像:
docker build -t getting-started .