如何在Docker容器之间共享数据
容器是一种使程序在从一个环境移到另一个环境时独立运行的方式。容器化则是包装容器的过程,使其更容易扩展,并增强其可移植性。
Docker容器使你能够从你的环境中快速开发和运行你的应用程序。
先决条件
为了开始工作,我们必须在我们的系统上安装Docker。
请注意,我们将在本教程中使用
Ubuntu 20.04。
创建一个独立的卷
Docker卷是附属于容器的系统文件,有助于持久保存数据。当人们想在不同的容器之间共享数据时,Docker卷也是至关重要的。
让我们开始吧。
我们将使用docker volume create 命令来创建一个卷,而不把它与任何容器联系起来。
让我们创建一个名为NewVol1 的卷。
docker volume create NewVol1
如果我们列出我们的输出,我们可以看到创建的卷。
docker volume ls
DRIVER VOLUME NAME
local NewVol1
接下来,我们需要从Ubuntu image 中设置一个新的容器。我们使用--rm 标志在用户退出时删除该容器。-v 标志将新的卷挂载起来。
卷的名称必须在冒号和绝对路径之后指定,如下所示。
docker run -ti --rm -v NewVol1:/newvol1 ubuntu
下面的代码段向你展示了如何在容器中向Docker卷写入数据。
root@77a92a143828:/# echo "Example1" > /newvol1/Example1.txt
我们使用下面的代码片断退出根目录。
root@77a92a143828:/# exit
为了检查我们的卷是否仍然驻留在我们的环境中,我们使用docker volume inspect 。
docker volume inspect NewVol1
输出结果是。
[
{
"CreatedAt": "2021-05-12T20:20:24+03:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/NewVol1/_data",
"Name": "NewVol1",
"Options": {},
"Scope": "local"
}
]
输出是JSON数组的格式。它显示了检查的timestamp 。Driver 和Scope 都在我们的本地系统中。
然而,Labels 和Options 是空的,因为我们没有指定它们。Mountpoint 显示了卷所处的路径。name 属性表示我们正在检查的卷。
接下来,让我们启动一个新的容器并附加NewVol1 。
docker run -ti --rm -v NewVol1:/newvol1 ubuntu
你可以检查内容,如下图所示。
docker run -ti --rm -v NewVol1:/newvol1 ubuntu
root@b4a69fffc60a:/# cat /newvol1/Example1.txt
Example1
root@b4a69fffc60a:/# exit
exit
从一个现有的带数据的目录创建一个卷
在这一步,我们将在一个带有数据的容器内创建一个卷。
在/var 路径,让我们建立一个容器并添加一个Docker卷。
docker run -ti --rm -v NewVol2:/var ubuntu
root@976fbd71c0a7:/# exit
exit
注意,
/var目录中的内容在Docker卷中是重复的。我们还将卷附加到最新的容器中,并退出当前目录。
我们正在使用ls ,而不是默认的bash ,以启动shell。
docker run --rm -v NewVol2:/newvol2 ubuntu ls newvol2
backups cache lib local lock log mail opt run spool tmp
newvol2 索引复制了/var 目录中的组件。
使用这种方法来附加/var/ ,有助于渲染图像。
在多个Docker容器之间共享数据
更多的时候,我们会希望各种容器挂载到类似的Docker卷。然而,Docker并不处理文件锁。为了将各种容器写入卷,容器的当前环境应该是一个支持共享数据存储的设备。
创建容器3和DataVolume3
我们使用docker run ,建立一个新的容器,名为Container3 ,如下图。
docker run -ti --name=Container3 -v NewVol3:/newvol3 ubuntu
然后我们在一个新文件中添加一些文本,如下图所示。
root@1ef4d68f08b2:/# echo "Shared container file" > /newvol3/Example3.txt
root@1ef4d68f08b2:/# exit
exit
然后我们退出容器并导航到主机终端,在那里我们创建一个新的容器,附加来自Container3 的数据卷。
创建容器4并附加来自容器3的卷
让我们把Container3 附加到新创建的Container4 ,如下图所示。
docker run -ti --name=Container4 --volumes-from Container3 ubuntu
如图所示,数据的一致性得到了检查。
root@d19c4e150495:/# cat /newvol3/Example3.txt
Shared container file
root@d19c4e150495:/#
在这一点上,让我们从Container4 附加一些文本,然后退出容器。
root@d19c4e150495:/# echo "Both containers can write to NewVol3" >> /newvol3/Example3.txt
root@d19c4e150495:/# exit
exit
随后,我们将检查我们的数据是否仍然存在于Container3 中。
容器4的变化
我们可以通过刷新Container3 来检查Docker卷中的变化。
docker start -ai Container3
下面的命令确认所有容器是否能够从Docker卷中读写,然后退出环境。
root@1ef4d68f08b2:/# cat /newvol3/Example3.txt
Shared container file
Both containers can write to NewVol3
root@1ef4d68f08b2:/# exit
exit
启动容器5并附加卷的只读性
如果一个容器已经被一个数据卷挂载,我们不会像典型的Linux文件那样卸载它。我们建立一个新的容器并使该卷成为只读。
在容器名称的后面加上:ro 标志,使其成为read-only ,如下图所示。
docker run -ti --name=Container5 --volumes-from Container3:ro ubuntu
我们通过尝试省略我们创建的文件来测试只读的突出性。
root@9b1678a2d548:/# rm /newvol3/Example3.txt
rm: cannot remove '/newvol3/Example3.txt': Read-only file system
root@9b1678a2d548:/# exit
exit
下面的命令清除了我们的测试容器和卷。
docker rm Container3 Container4 Container5
docker volume rm NewVol3
结论
在本教程中,我们已经学会了如何创建一个独立的Docker卷,当容器被删除时,它可以持续保存数据。它还有利于在不同的容器之间共享数据。
文件锁定机制可以减少数据损坏。最后,我们还学习了如何挂载一个共享卷并使其成为只读。