如何在Docker容器之间共享数据

介绍

Docker是一种流行的容器化工具,用于向软件应用程序提供包含运行所需的所有内容的文件系统。使用Docker容器确保软件将以相同的方式运行,而不管其部署在哪里,因为它的运行时环境无残忍地一致。 一般来说,Docker容器是短暂的,只要在容器中发出的命令完成就运行。然而,有时,应用程序需要在容器被删除后共享对数据的访问或持久化数据。数据库,网站的用户生成的内容和日志文件只是一些数据的示例,这些数据在Docker镜像中是不切实际或不可能包含的,但是哪些应用程序需要访问。 Docker卷提供对数据的持久访问。

先决条件

要跟随这篇文章,你将需要一个Ubuntu 16.04服务器,具有以下: 注:即使先决条件给出了在Ubuntu 16.04安装Docker指令, docker本文中Docker数据量的命令应该在其它操作系统上,只要Docker已安装并运行sudo用户已被添加到docker组。 Docker卷可以在创建容器的同一命令中创建和附加,也可以独立于任何容器创建,然后再连接。在本文中,我们将介绍在容器之间共享数据的四种不同方法。

1 - 创建独立卷

在Docker的1.9版本中引入的 docker volume create命令,可以没有它与任何特定的容器创建卷。 我们将使用这个命令来添加一个名为量 DataVolume1
docker volume create --name DataVolume1
将显示名称,表示命令成功。
OutputDataVolume1
为了使用量,我们将创建一个从Ubuntu的镜像新的容器,使用 --rm标志,当我们退出时自动删除。 我们将使用 -v安装新卷。 -v需要大卷,一个冒号,然后是绝对路径所在的卷应出现在容器内的名称。 如果路径中的目录不作为映像的一部分存在,那么将在命令运行时创建它们。 如果他们 存在,安装的卷将隐藏现有内容。
docker run -ti --rm -v DataVolume1:/datavolume1 ubuntu
当我们在那里,我们将写一些数据到卷:
echo "Example1" > /datavolume1/Example1.txt
因为我们使用了 --rm标志,我们的容器时,将自动退出我们删除。但是,我们的卷仍然可以访问。
exit
我们可以验证卷存在与系统上 docker volume inspect
docker volume inspect DataVolume1
Output[
    {
        "Name": "DataVolume1",
        "Driver": "local",
        "Mountpoint": "/var/lib/docker/volumes/datavolume1/_data",
        "Labels": null,
        "Scope": "local"
    }
]
注意:我们甚至可以看一下数据在主机上列为安装点的路径。但是,我们应该避免更改它,因为它可能导致数据损坏,如果应用程序或容器不知道更改。 接下来,让我们开始一个新的容器,并附加 DataVolume1
docker run --rm -ti -v DataVolume1:/datavolume1 ubuntu
cat /datavolume1/Example1.txt
OutputExample1
让我们退出容器。
exit
在此示例中,我们创建了一个卷,将其附加到容器,并验证其持久性。

2 - 创建在容器删除时持续存在的卷

在下一个示例中,我们将创建一个与容器同时的卷,删除容器,然后将卷附加到一个新容器。 我们将使用 docker run命令创建使用基地的新容器 ubuntu形象。 -t会给我们一个终端, -i将使我们能够与它进行交互。 为了清楚起见,我们将使用 --name识别容器。 接下来,我们将添加 -v标志创建 我们将使用 -v来创建新卷。 我们将其命名为 DataVolume2 。 我们将使用冒号将此名称与卷应该在容器中加载的路径分开。 最后,我们将指定基Ubuntu的形象,并依靠在默认的命令 Ubuntu的基本图像的Docker文件bash ,我们放到一个外壳。
docker run -ti --name=Container2 -v DataVolume2:/datavolume2 ubuntu
注: -v标志是非常灵活的。 它可以绑定或命名一个卷,只需稍微调整语法。 如果第一个参数一个开始 /~/你要创建一个绑定装入。删除它,并且命名卷。例如:
  • -v /path:/path/in/container装入主机目录, /path/path/in/container
  • -v path:/path/in/container创建一个名为量path与主机没有任何关系。
欲了解更多关于从主机bindmounting的目录,请参阅 如何Docker容器和主机之间的数据共享 当我们在那里,我们将写一些数据到卷:
echo "Example2" > /datavolume2/Example2.txt
cat /datavolume2/Example2.txt
OutputExample2
我们将退出容器:
exit
当我们重新启动它,卷将自动安装。
docker start -ai Container2
让我们验证该卷是否已安装,并且我们的数据仍然存在:
cat /datavolume2/Example2.txt
OutputExample2
最后,让我们退出并清理。
exit
Docker不会让我们删除一个容器引用的卷。让我们看看当我们尝试时会发生什么:
docker volume rm DataVolume2
该消息告诉我们,卷仍在使用,并提供容器ID的长版本:
OutputError response from daemon: Unable to remove volume, 
volume still in use: remove DataVolume2: volume is in use - 
[719f98391ecf1d6f0f053ffea1bbd84cd2dc9cf6d31d5a4f348c60d98392804c]
我们可以使用ID来删除容器:
docker rm 719f98391ecf1d6f0f053ffea1bbd84cd2dc9cf6d31d5a4f348c60d98392804c
Output719f98391ecf1d6f0f053ffea1bbd84cd2dc9cf6d31d5a4f348c60d98392804c
删除容器不会影响卷。我们可以看到,它仍然存在于系统中通过列出与卷 docker volume ls
docker volume ls
OutputDRIVER              VOLUME NAME
local               DataVolume2
并且我们可以使用 docker volume rm将其删除。
docker volume rm DataVolume2
在此示例中,我们在创建容器的同时创建了一个空数据卷。在下一个示例中,我们将探讨在使用已经包含数据的容器目录创建卷时会发生什么。

3 - 使用数据从现有目录创建卷

一般地,用独立创建卷 docker volume create和制作一个在创建一个容器是等效的,但有一个例外。 如果我们创建同时一个卷作为我们创建一个容器 我们提供的路径包含该基本图像中的数据,该数据将被复制到该卷的目录。 作为一个例子,我们将创建一个容器,并在其中添加数据量 /var ,其中包含基本的图像数据的目录:
docker run -ti --rm -v DataVolume3:/var ubuntu
将来自基本映像的/ var目录的所有内容复制到卷中,我们可以将该卷挂载到新容器中。这一次,而不是依赖于基础映像的默认 bash命令,我们会发出我们自己的 ls命令,该命令将显示卷的内容,而无需输入外壳:
docker run --rm -v DataVolume3:/datavolume3 ubuntu ls DataVolume3
DataVolume3具有的基本映像的内容拷贝 /var目录:
Outputbackups
cache
lib
local
lock
log
mail
opt
run
spool
tmp
这是不可能的,我们将要安装 /var/这样,但如果我们制作我们自己的形象,并希望有一个简单的方法来保存数据,这会很有帮助。在下一个示例中,我们将演示如何在多个容器之间共享卷。

4 - 在多个Docker容器之间共享数据

到目前为止,我们一次将一个卷附加到一个容器。但是经常,我们需要多个容器附加到同一个数据卷。这是相对直接的完成,但有一个关键的警告:这时,Docker不处理文件锁定。如果需要多个容器写入到卷,这些容器运行的应用程序的设计 必须写入共享数据存储,以防止数据损坏。

创建Container4和DataVolume4

使用 docker run到创建一个名为新的容器 Container4附有数据卷。
docker run -ti --name=Container4 -v DataVolume4:/datavolume4 ubuntu 
接下来,我们将创建一个文件并添加一些文本:
echo "This file is shared between containers" > /datavolume4/Example4.txt
然后,我们将退出容器。
exit
这将返回到主机命令提示符,在那里我们将创建一个新的容器,从Container4挂载数据卷

从Container4创建Container5和装载卷

我们将创建Container5,并从Container4挂载卷:
docker run -ti --name=Container5 --volumes-from Container4 ubuntu
cat /datavolume4/Example4.txt
OutputThis file is shared between containers
现在让我们从第二个容器中添加一些文本:
echo "Both containers can write to DataVolume4" >> /datavolume4/Example4.txt
最后,我们将退出容器:
exit
接下来,我们将检查我们的数据是否仍然存在Container4。

查看Container5中所做的更改

让我们通过重新启动Container4来检查由Container5写入数据卷的更改:
docker start -ai Container4
cat /datavolume4/Example4.txt
cat /DataVolume4/Example4.txt
OutputThis file is shared between containers
Both containers can write to DataVolume4
现在我们已经验证了这两个容器都能够从数据卷读取和写入,我们将退出该容器:
exit
再次,Docker不处理任何文件锁定,因此应用程序 必须考虑文件锁定自己。 它可以装入一个容积Docker为只读,以确保数据损坏当容器需要通过添加只读访问不会发生意外 :ro 。让我们看看这是如何工作的。

启动容器6并将卷挂载为只读

一旦一个卷被安装在一个容器中,而不是象我们在典型的Linux文件系统那样卸载它,我们改为创建一个新的容器,如果需要的话,删除以前的容器。为了使卷只读,我们追加 :ro到容器名称的结尾:
docker run -ti --name=Container6 --volumes-from Container4:ro ubuntu
我们将通过尝试删除示例文件来检查只读状态:
rm /datavolume4/Example4.txt
Outputrm: cannot remove '/datavolume4/Example4.txt': Read-only file system
最后,我们将退出容器并清理我们的测试容器和卷:
exit
现在我们完成了,让我们清理我们的容器和卷:
docker rm Container4 Container5 Container6
docker volume rm DataVolume4
在本例中,我们已经展示了如何使用数据卷在两个容器之间共享数据,以及如何以只读方式挂载数据卷。

结论

在本教程中,我们创建了一个数据卷,允许通过删除容器来保留数据。我们已经在容器之间共享了数据卷,需要注意的是,应用程序需要设计为处理文件锁定以防止数据损坏。最后,我们展示了如何以只读模式挂载共享卷。如果你有兴趣了解容器和主机系统之间共享数据,请参阅 如何将Docker容器和主机之间的数据共享
赞(52) 打赏
未经允许不得转载:优客志 » 系统运维
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏