如何在 Ubuntu 22.04 上的 Docker 容器之间共享数据

介绍

Docker 是一个流行的集装箱化工具,用于提供软件应用程序的文件系统,其中包含他们运行所需的一切。

通常情况下,Docker 容器是短暂的,运行的时间是需要在容器中发出的命令完成的时间。然而,有时,应用程序需要共享数据访问或在容器被删除后持续数据。 数据库、用户生成的网站内容和日志文件只是一些不切实际或不可能在Docker 图像中包含的数据的例子,但哪些应用程序需要访问。

Docker 卷可以用创建容器的相同命令创建和附加,也可以独立创建任何容器并稍后附加。

前提条件

要遵循这篇文章,你需要一个 Ubuntu 22.04 服务器,具有以下内容:

<$>[注] **注:**虽然前提规定在Ubuntu 22.04上安装Docker,但本文中的Docker命令对于Docker数据量应该在其他操作系统上工作,只要Docker安装,并将 sudo用户添加到Docker组。

步骤 1 – 创建一个独立的卷

在Docker 1.9 版本中引入的Docker 创建卷命令允许您创建卷,而不将其与任何特定容器相关联。

1[environment local]
2docker volume create --name DataVolume1

显示命名,表示命令成功:

1[secondary_label Output]
2[environment local]
3DataVolume1

要利用卷,你将从Ubuntu图像中创建一个新的容器,使用--rm旗帜自动删除它,当你离开时。你还将使用-v来安装新的卷。-v需要卷的名称,一个子,然后绝对路径到容器内部应该出现的卷。如果路径中的目录不存在作为图像的一部分,它们将在命令运行时创建。

1[environment local]
2docker run -ti --rm -v DataVolume1:/datavolume1 ubuntu

在容器中,将一些数据写入体积:

1[environment second]
2echo "Example1" > /datavolume1/Example1.txt

由于您使用了--rm旗,您的容器将在您离开时自动删除,但您的音量仍然可访问。

1[environment second]
2exit

您可以通过docker Volume Inspect来验证系统中是否存在的音量:

1[environment local]
2docker volume inspect DataVolume1
 1[secondary_label Output]
 2[environment local]
 3[
 4    {
 5        "CreatedAt": "2018-07-11T16:57:54Z",
 6        "Driver": "local",
 7        "Labels": {},
 8        "Mountpoint": "/var/lib/docker/volumes/DataVolume1/_data",
 9        "Name": "DataVolume1",
10        "Options": {},
11        "Scope": "local"
12    }
13]

<$>[注] **注:**您甚至可以在列出为山点的路径上查看主机上的数据,但您应该避免更改它,因为如果应用程序或容器不知道变化,则可能会导致数据损坏。

接下来,启动一个新的容器并添加DataVolume1:

1[environment local]
2docker run --rm -ti -v DataVolume1:/datavolume1 ubuntu

查看内容:

1[environment third]
2cat /datavolume1/Example1.txt
1[secondary_label Output]
2[environment third]
3Example1

走出容器:

1[environment third]
2exit

在此示例中,您创建了一个卷,将其附加到容器中,并验证其持久性。

步骤 2 — 创建一个在容器被移除时仍然存在的卷

在下一个示例中,您将与容器同时创建一个体积,删除容器,然后将体积附加到新的容器中。

您将使用docker run命令创建一个新的容器,使用Ubuntu基础图像。-t将给我们一个终端,-i将允许我们与它进行交互。

v旗帜将允许我们创建一个新的卷,你将称之为DataVolume2。你将使用一个子来将这个名称与容器中应该安装的卷的路径分开。最后,你将指定基础Ubuntu图像,并依赖在Ubuntu基础图像的Docker文件(https://github.com/dockerfile/ubuntu/blob/master/Dockerfile#L32)中的默认命令,‘bash’,以使我们陷入一个壳:

1[environment local]
2docker run -ti --name=Container2 -v DataVolume2:/datavolume2 ubuntu

<$>[注] 注: -v 旗是非常灵活的。它可以连接或命名一个卷,只需对语法进行轻微调整。如果第一个参数以 /~/ 开头,你正在创建一个连接。

  • -v /path:/path/in/container 安装了主机目录, /path/path/in/container
  • -v path:/path/in/container 创建了一个名为 path 的卷,与主机无关。

有关从主机连接目录的更多信息,请参阅 如何在 Docker 容器和主机之间共享数据 <$>

在容器中,你会写一些数据到卷:

1[environment second]
2echo "Example2" > /datavolume2/Example2.txt
3cat /datavolume2/Example2.txt
1[secondary_label Output]
2[environment second]
3Example2

走出容器:

1[environment second]
2exit

当您重新启动容器时,音量将自动安装:

1[environment local]
2docker start -ai Container2

检查音量是否确实安装,并且您的数据仍然存在:

1[environment second]
2cat /datavolume2/Example2.txt
1[secondary_label Output]
2[environment second]
3Example2

最后,出门和清理:

1[environment second]
2exit

Docker 不允许我们删除一个卷,如果它是由容器引用。

1[environment local]
2docker volume rm DataVolume2

该消息告诉我们,该卷仍在使用,并提供容器ID的长版本:

1[secondary_label Output]
2[environment local]
3Error response from daemon: unable to remove volume: remove DataVolume2: volume is in use - [d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63]

您可以使用上面的错误消息中的ID来删除容器:

1[environment local]
2docker rm d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63
1[secondary_label Output]
2[environment local]
3d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63

删除容器不会影响体积. 您可以通过列出docker volume ls的体积来看到它仍然存在于系统中:

1[environment local]
2docker volume ls
1[secondary_label Output]
2[environment local]
3DRIVER VOLUME NAME
4local DataVolume2

您可以使用docker volume rm来删除它:

1[environment local]
2docker volume rm DataVolume2

在本示例中,您在创建容器的同时创建了一个空的数据量. 在下一个示例中,您将探索当您使用已包含数据的容器目录创建一个卷时会发生什么。

步骤 3 — 创建来自数据的现有目录的卷

一般来说,使用docker 创建卷独立创建卷和在创建容器时创建卷等同于一个例外,如果你在创建容器时同时创建卷 and 你提供了包含数据的目录的路径,该数据将被复制到卷中。

例如,您将创建一个容器并在 /var 中添加数据量,该目录包含基础图像中的数据:

1[environment local]
2docker run -ti --rm -v DataVolume3:/var ubuntu

从基础图像的/var目录的所有内容被复制到卷中,你可以将该卷装在一个新的容器中。

退出当前的容器:

1[environment second]
2exit

这次,而不是依靠基本图像的默认bash命令,您将发出自己的ls命令,该命令将显示卷的内容而不输入壳:

1[environment local]
2docker run --rm -v DataVolume3:/datavolume3 ubuntu ls datavolume3

该目录 datavolume3现在有基础图像 /var 目录的内容的副本:

 1[secondary_label Output]
 2[environment local]
 3backups
 4cache
 5lib
 6local
 7lock
 8log
 9mail
10opt
11run
12spool
13tmp

您不太可能希望以这种方式安装 /var/,但如果您已经创建了自己的图像,并且想要一个简单的方法来保存数据,则可以有帮助。

第 4 步:在多个 Docker 容器之间共享数据

到目前为止,您已将一个卷连接到一个容器一次. 通常,您将希望多个容器连接到相同的数据量. 这是相对简单的,但有一个关键的警告:在这个时候,Docker 不会处理文件锁定。

创建 Container4 和 DataVolume4

使用docker run创建一个名为Container4的新容器,附加数据量:

1[environment local]
2docker run -ti --name=Container4 -v DataVolume4:/datavolume4 ubuntu

接下来你会创建一个文件并添加一些文本:

1[environment second]
2echo "This file is shared between containers" > /datavolume4/Example4.txt

然后,你会离开容器:

1[environment second]
2exit

这会让我们回到主机命令提示,在那里你会创建一个新的容器,将数据量从Container4中安装起来。

从集装箱4创建集装箱5和集装卷

您将创建Container5,并从Container4中安装卷:

1[environment local]
2docker run -ti --name=Container5 --volumes-from Container4 ubuntu

检查数据持久性:

1[environment third]
2cat /datavolume4/Example4.txt
1[secondary_label Output]
2[environment third]
3This file is shared between containers

现在,添加一些从Container5的文本:

1[environment third]
2echo "Both containers can write to DataVolume4" >> /datavolume4/Example4.txt

最后,您将离开容器:

1[environment third]
2exit

接下来,您将检查您的数据是否仍然存在于Container4

查看在集装箱5中做的更改

现在,检查通过重新启动Container4来写入Container5数据量的更改:

1[environment local]
2docker start -ai Container4

查看更改:

1[environment second]
2cat /datavolume4/Example4.txt
1[secondary_label Output]
2[environment second]
3This file is shared between containers
4Both containers can write to DataVolume4

现在,您已经验证了两个容器能够从数据量中读取和写入,您将离开容器:

1[environment second]
2exit

再次,Docker 无法处理任何文件锁定,因此应用程序必须为文件锁定自己负责. 可以将 Docker 卷设置为仅读式,以确保数据破坏不会偶然发生,当容器需要仅读式访问时通过添加 :ro

启动集装箱 6 并安装 Volume Read-Only

一旦一个卷被安装在一个容器中,而不是像你用典型的Linux文件系统一样卸载它,你可以创建一个新的容器以你想要的方式安装,如果需要,删除以前的容器。

1[environment local]
2docker run -ti --name=Container6 --volumes-from Container4:ro ubuntu

您将通过尝试删除示例文件来检查仅读状态:

1[environment fourth]
2rm /datavolume4/Example4.txt
1[secondary_label Output]
2[environment fourth]
3rm: cannot remove '/datavolume4/Example4.txt': Read-only file system

最后,您将离开容器并清理测试容器和卷:

1[environment fourth]
2exit

现在你已经完成了,清理你的容器和体积:

1[environment local]
2docker rm Container4 Container5 Container6
3docker volume rm DataVolume4

在本示例中,您展示了如何使用数据量在两个容器之间共享数据,以及如何将数据量设置为只读。

结论

在本教程中,您创建了一个数据量,允许数据通过删除一个容器继续存在。您在容器之间共享数据量,并警告说应用程序需要设计以处理文件锁定以防止数据破坏。

Published At
Categories with 技术
comments powered by Disqus