掌握 Docker 卷
对于刚开始使用 Docker 的人,我写了一些关于如何像容器一样思考的文章,我相信这是使用 Docker 的重要思维方式,也是在开发中正确使用 Docker 的重要思维方式。
但是,如果您想进一步掌握 Docker,那么了解Docker 中的卷和网络如何工作非常重要。
在这篇文章中,我将引导您了解卷的基础知识,而网络部分则留到另一篇文章中介绍。
容器是短暂的
需要注意的是,容器是短暂的。只要容器执行完命令,它就会彻底“关闭”。
=> docker run node ls
bin
boot
dev
etc
home
lib
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
它使用图像节点启动一个新容器,并ls在容器内执行命令(列出文件和目录)。
该命令给出输出并完成。命令完成后,容器将关闭,其所有数据将丢失。
执行 Javascript 程序
假设我们有一个包含非常基本的 Javascript 程序的文件:
helloWorld.js
greeting = (message) => {
console.log(message)
}
greeting("Hello, world")
我们如何使用容器运行这个程序?可以尝试这样做:
docker run node node helloWorld.js
...这引发了错误:
Error: Cannot find module '/app/helloWorld.js'
...
这是因为容器是隔离的并且不共享相同的主机文件系统。
在主机和容器之间同步数据
我们必须将文件helloWorld.js与容器同步。Docker 提供了一种挂载卷的方法,这意味着:
我想将目录或文件从主机挂载到容器,这样在主机中所做的每个更改都将镜像到容器,反之亦然。
你在主机中更改文件/目录,容器也会看到这些变化。你在容器中更改文件/目录,主机也会看到这些变化。
helloWorld.js让我们与容器同步:
docker run
-v $(pwd)/docker-101/helloWorld.js:/app/helloWorld.js
node
node /app/helloWorld.js
Hello, world
...在哪里:
- pwd指的是当前目录的完整路径名
- -v {hostPath}:{containerPath}将文件/目录挂载到容器
- 节点是图像
- node /app/helloWorld.js使用容器内定义的路径执行命令,
/app/helloWorld.js
一个真实的项目
假设我们有一个这样的项目树:
/docker-101
/src
/components
components.js
index.js
从目录内部docker-101,我们想要使用该文件运行一个容器,但文件夹index.js中的所有文件也必须位于容器应用程序中。src
docker run
-v $(pwd):/app
node
node /app/index.js
当前目录中的所有文件都pwd将挂载到/app容器内。
如果我们想进入容器并从那里操作文件怎么办?
docker run
-it
-v $(pwd):/app
node
bash
...在哪里:
- -它指示 Docker 保持容器终端(bash/shell)打开
- bash在容器内打开一个新的 bash/shell
root@8dcbfa6d777c:/# cd /app
root@8dcbfa6d777c:/app# ls
index.js src
root@8dcbfa6d777c:/app# touch new-file.js
root@8dcbfa6d777c:/app# ls
index.js new-file.js src
root@8dcbfa6d777c:/app# exit
exit
现在,退出容器后,如果我们ls 从主机执行,我们会得到:
index.js new-file.js src
这种类型的体积称为路径体积。
使用挂载选项
挂载卷的另一种方法是使用--mount选项,该选项指定挂载的类型、源和目标。
docker run
--mount type=bind,source=$(pwd),target=/app
node
node /app/helloWorld.js
更mount明确,但在大多数情况下使用-v就足够了。
另一个真实的例子
假设我们想打印当前时间的时间戳。有很多方法可以实现,但现在我们将使用Underscore库。
index.js
var _ = require('underscore');
console.log(_.now())
我们执行docker run -it -v $(pwd):/app node node /app/index.js,得到以下错误:
Error: Cannot find module 'underscore'
显然,我们必须将underscore依赖项添加到我们的项目中。让我们使用以下命令来完成npm:
docker run
-v $(pwd):/app
-w /app
node
npm add underscore
added 1 package, and audited 2 packages in 2s
注意-w /app,它表示工作目录,我们告诉 Docker 从该目录内执行命令。在我们的例子中,该命令将在容器内的目录npm add underscore中执行。/app
现在,我们可以运行index.js:
docker run
-v $(pwd):/app
-w /app
node
node index.js
1644018496251
想要一些 NPM 缓存吗?
有时我们需要使用缓存来加速 npm 进程。在容器内部,默认情况下,npm存储缓存在/root/.npm。你可以运行以下命令进行检查:
npm config get cache
=> /root/.npm
目前,我们仅同步-v $(pwd):/app卷。当容器将 npm 缓存写入时/root/.npm,我们不会同步回主机。
我们了解到我们可以将多个卷安装到容器中,所以让我们这样做:
docker run
-v $(pwd):/app
-v $(pwd)/npm_cache:/root/.npm <---- sync the NPM cache
-w /app
node
npm install underscore
当我们ls从主机执行时,我们得到以下内容:
index.js node_modules npm_cache package-lock.json package.json src
但是,我们不想在项目中跟踪“npm_cache”文件夹。这不关我们的事。
如果我们想将这样的缓存存储在主机的另一个路径中,因此我们不关心它存储在哪里,该怎么办?
Docker 提供了一种特殊类型的 Volume,它在 Host 中的路径由 Docker 选择,因此我们唯一需要知道的就是它的名称。Docker 知道它的位置,但我们并不关心。
是的,它们被称为命名卷。
docker volume create my-volume
docker volume inspect my-volume
[
{
"CreatedAt": "2022-02-05T00:47:59Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
"Name": "my-volume",
"Options": {},
"Scope": "local"
}
]
这Mountpoint是主机中的确切路径。因此,每个使用此卷的容器都会将其数据直接同步到此挂载点,而我们则可以通过在其他地方使用其名称“my-volume”来管理和了解该卷。
在我们的下划线示例中,我们也可以使用命名卷启动容器:
docker run
-v $(pwd):/app
-v npm_cache:/root/.npm <---- named volume in the Host
-w /app
node
npm install underscore
这样,Docker 将创建一个名为的卷npm_cache并将其挂载到容器中/root/.npm。
不相信?你自己去看看吧:
docker volume inspect npm_cache
[
{
"CreatedAt": "2022-02-05T00:51:24Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/npm_cache/_data",
"Name": "npm_cache",
"Options": null,
"Scope": "local"
}
]
太棒了!现在清晰多了,因为我们保持了 npm 进程的加速。
docker run
-v $(pwd):/app
-v npm_cache:/root/.npm
-w /app
node
node index.js
1644022388847
总结
在本文中,我们学习了如何在 Docker 中使用路径卷和命名卷。
当我们想要跟踪主机中的路径(即安装我们正在处理的整个项目)时,路径卷非常有用。
当我们不想跟踪主机中的路径,而是利用 Docker 为我们选择路径时,命名卷非常方便mountpoint,即使用 NPM、Yarn、Ruby bundler、Python 包等的缓存。
后端开发教程 - Java、Spring Boot 实战 - msg200.com