介绍
Docker 是一个容器平台,它是一个轻量级、虚拟化、便携式、软件定义的标准化环境,允许软件与物理宿主机上运行的其他软件隔离运行。Docker 是软件开发中持续开发和集成方面的一个决定性组件。通过提供一致的运行时环境,Docker 确保软件无论部署在哪个物理宿主机上,其行为都是相同的。为了深入了解 Docker 生态系统的概览,请查看这篇文章.
虽然 Docker 容器是自包含的,但有时它们需要在容器停止后共享对数据的访问或将数据持久化到磁盘。数据可以是数据库、日志文件或用户生成的数据的形式。此类数据无法包含在 Docker 镜像配置文件中,但它需要可用于您的应用程序以按预期运行。在 Docker 容器中共享和持久化数据是由 Docker 卷 处理的。Docker 卷可以在容器创建期间创建,也可以在以后创建并附加到容器。 在本教程中,我们将讨论在容器之间共享数据的四种不同方法。
前提条件
- 设置一台运行 Ubuntu 20.04 的服务器 并 创建一个具有 sudo 特权的非 root 用户。使用该非 root 用户登录以继续以下步骤。
- 安装 Docker——我们有一个关于 如何在 Ubuntu 上安装和操作 Docker 的教程,您需要按照步骤 1、2、3 和 4 进行操作。这适用于任何 Ubuntu 发行版。
请注意,虽然我们使用的是 Ubuntu 20.04,但只要安装了 Docker 并按照上述前提条件将 sudo 用户添加到 docker 用户组中,Docker 的指令和命令就可以在任何其他操作系统上运行。
步骤 1:创建独立的 Docker 卷
我们将首先创建与任何 Docker 容器无关的独立卷。为此,我们有自 Docker 1.9 版本中引入的命令 docker volume create。输入以下命令以创建一个名为 Step1DataVolume :
|
1 |
docker volume create --name Step1DataVolume |
您应该会看到以下输出,表明卷创建成功:
![]()
现在我们有了一个独立的卷,我们可以从官方 Ubuntu 镜像创建一个新容器作为示例来使用它。输入以下命令以创建容器并挂载该卷:
|
1 |
docker run -ti --rm -v Step1DataVolume:/Step1DataVolume ubuntu |
在此命令中, --rm 标志将在退出后自动删除容器。而 -v 标志用于指定并挂载卷。 -v 标志接受卷的名称、一个英文冒号以及该卷在容器中应出现的绝对路径。请记住,当命令运行时,如果路径中指定的目录不存在,它们将被创建。如果它们已经存在,挂载的卷将隐藏现有内容。对于 -ti 标志, -t 允许访问终端,而 -i 允许我们通过终端与容器进行交互。
在容器内部时,运行以下命令向卷中写入一些数据:
|
1 |
echo "Step One Sample Text" > /Step1DataVolume/StepOne.txt |
输入 exit 并按下 enter 以退出容器。如前所述,由于 --rm 标志,容器在您退出时会自动删除,但是,该卷仍然可以访问。
要验证该卷是否仍然存在,您可以使用 docker volume inspect 命令:
|
1 |
docker volume inspect Step1DataVolume |
您应该会看到以下输出:

接下来,让我们创建一个新容器。首先,挂载该卷并查看我们是否可以访问在先前容器中创建的文本。输入以下命令,使用 ubuntu 镜像:
|
1 |
docker run -ti --rm -v Step1DataVolume:/Step1DataVolume ubuntu |
在容器内部,运行以下命令以验证 StepOne.txt 文件是否存在:
|
1 |
cat /Step1DataVolume/StepOne.txt |
您应该会看到类似的输出:

接下来,输入 exit 并按 Enter 以退出容器。在这一步中,您学习了如何使用独立的 Docker 数据卷来处理数据持久化,以及如何将数据卷挂载到容器中。
第 2 步:创建一个在删除容器时仍能持久化数据的 Docker 数据卷
在这一步中,我们将使用单个命令在创建容器的同时创建数据卷。然后,我们将删除该容器并将该数据卷挂载到一个新容器中。该命令与在第 1 步中使用的命令类似,但是,我们添加了一个标志 --name,以指定容器的名称:
|
1 |
docker run -ti --name=Step2Container1 -v Step2DataVolume:/Step2DataVolume ubuntu |
在容器内部时,输入以下命令将数据写入数据卷并验证数据是否存在:
|
1 2 3 |
echo "Step Two Sample Text" > /Step2DataVolume/StepTwo.txt cat /Step2DataVolume/StepTwo.txt |
以下是这三个命令的输出:

接下来,退出容器。当您使用以下命令重新启动容器时,数据卷将自动挂载:
|
1 |
docker start -ai Step2Container1 |
在容器内部,通过使用以下命令检查 StepTwo.txt 文件是否存在,以验证数据卷是否已挂载:
|
1 |
cat /Step2DataVolume/StepTwo.txt |
以下是输出:

您现在可以退出容器了。Docker 会阻止删除其他容器正在引用的数据卷。您可以尝试使用以下命令删除该数据卷:
|
1 |
docker volume rm Step2DataVolume |
您应该在输出中看到错误消息:
![]()
让我们使用输出中显示的容器 ID,通过 docker rm 命令来删除容器:
|
1 |
docker rm e3932e65e484bbf4524ca8de1b1dd99c4e92c12f92a9d6b0567a643d0aa6bb2d |
将突出显示的 container id 替换为 id(您终端中显示的容器 ID)。该命令会删除容器,但不会删除我们创建的数据卷。您可以使用 docker volume ls 命令列出可用数据卷以进行验证:
|
1 |
docker volume ls |
以下是输出:

要删除在Step 2中创建的容器,请输入以下命令:
|
1 |
docker volume rm Step2DataVolume |
在这一步中,您成功地在创建容器的同时创建了一个 Docker 数据卷。让我们看看如何从包含数据的现有目录中创建数据卷。
第 3 步:从包含数据的现有目录中创建 Docker 数据卷
如果您想将数据复制到数据卷中,可以在创建容器的同时创建数据卷,并提供基础镜像中包含数据的目录路径。在下面的命令中,我们创建了一个容器,并在 /var 处添加了一个数据卷,这是基础镜像中包含数据的目录:
|
1 |
docker run -ti --rm -v Step3DataVolume:/var ubuntu |
当命令运行时,基础镜像的 /var 目录中的内容将被复制到该数据卷中。该数据卷可以挂载到新容器中。接下来,退出容器:

输入以下命令以创建容器、挂载数据卷,并使用 ls 命令列出数据卷的内容:
|
1 |
docker run --rm -v Step3DataVolume:/Step3DataVolume ubuntu ls Step3DataVolume |
您应该会从该命令中看到类似的输出,这是基础镜像中 /var 目录内容的副本,现在已在 Step3DataVolume:

当挂载 /var 目录(如我们在本例中所做的那样)可能不切实际,但它有助于我们理解,您可以将自定义镜像中创建的任何目录挂载到 Docker 数据卷,以便其他容器可以使用这些数据。
步骤 4:在多个 Docker 容器之间共享数据
在大多数情况下,您会希望多个容器访问同一个 Docker 数据卷中的数据。在之前的示例中,我们只将数据卷挂载到了一个容器。现在,您将学习如何将数据卷挂载到多个容器。虽然您可以轻松实现这一点,但 Docker 并不处理文件锁定。对于向同一个数据卷写入数据的多个容器,您必须单独设计在这些容器中运行的应用程序,以处理对共享数据存储的写入,从而避免数据损坏。
- 创建 Step4Container1 和 Step4DataVolume
使用 docker run 命令并带有 --name 标志来创建一个命名的容器:
|
1 |
docker run -ti --name=Step4Container1 -v Step4DataVolume:/Step4DataVolume ubuntu |
在容器内部,运行以下命令来创建一个文本文件并添加一些文本:
|
1 |
echo "Step Four Sample Text" > /Step4DataVolume/StepFour.txt |
之后,退出容器并返回宿主机环境。现在,我们想创建另一个容器,并挂载来自 Step4Container1 到它上面。
- 创建 Step4Container2 并挂载来自容器 Step4Container1
执行以下命令以创建 Step4Container2 并挂载来自 Step4Container1:
|
1 |
docker run -ti --name=Step4Container2 --volumes-from Step4Container1 ubuntu |
在容器内部,使用 cat 命令来验证数据持久化:
|
1 |
cat /Step4DataVolume/StepFour.txt |
您应该会看到以下输出:

我们可以从 Step4Container2 向该文件追加更多文本,方法是输入以下命令:
|
1 |
echo "We are appending text while inside Step4Container2" >> /Step4DataVolume/StepFour.txt |
在此之后退出容器,我们将返回 Step4Container1 以检查数据是否仍然存在。
- 验证不同容器之间在 Docker 数据卷中所做的更改
要查看更改,您首先需要重启 Step4Container1 ,使用以下命令:
|
1 |
docker start -ai Step4Container1 |
使用以下命令检查更改:
|
1 |
cat /Step4DataVolume/StepFour.txt |
您应该会看到类似于下图的输出:

一旦您验证了两个容器都可以对同一个数据卷进行读写,您现在就可以退出容器了。如前所述,Docker 并不处理文件锁定,应该由运行在容器内部的应用程序逻辑来处理对共享数据存储的读写访问。Docker 允许将数据卷挂载为只读,以防止仅需要只读访问的容器意外损坏数据,方法是添加 :ro ,如下一个示例所示。
- 将数据卷以只读方式挂载到 Docker 容器
在本例中,我们将创建一个名为 Step4Container3 的容器。在创建命令中,我们挂载来自 Step4Container1 并添加 :ro 以指定该容器具有只读访问权限,但无法写入该数据卷。在终端中执行以下命令:
|
1 |
docker run -ti --name=Step4Container3 --volumes-from Step4Container1:ro ubuntu |
进入容器后,您可以通过输入以下命令来读取数据卷中的文本文件:
|
1 |
cat /Step4DataVolume/StepFour.txt |

但是,如果您尝试使用以下命令删除该文件:
|
1 |
rm /Step4DataVolume/StepFour.txt |
您将在终端中看到如下错误信息:
![]()
验证读写权限后,您可以退出容器。如果您想清理本教程中创建的容器和卷,请运行以下命令:
|
1 2 3 |
docker rm Step4Container1 Step4Container2 Step4Container3 docker volume rm Step4DataVolume |
在这一步中,您学习了如何使用 Docker 卷在多个容器之间共享数据,以及如何将数据卷以只读方式挂载到容器中。
总结
在本教程中,您创建了一些 Docker 卷,并学习了如何在 Docker 容器之间共享数据。在处理容器之间的数据共享时,我们注意到,由于 Docker 没有实现文件锁处理,因此容器内部的单个应用逻辑必须处理文件锁,以防止在写入共享数据存储时发生数据损坏。
有关利用 Docker 的更多资源,您可能想查看更多教程,就在 我们的博客:
- 如何在 Docker 容器与主机之间共享数据
- 清理 Docker 资源 – 镜像、容器和卷
- 使用 Docker Compose 部署 Laravel、Nginx 和 MySQL
- 在 CentOS 7 上安装和设置 Docker
祝您使用愉快!
评论
暂无评论。发表第一条评论吧。