介绍
Docker 是一个流行的集装箱化工具,用于提供软件应用程序的文件系统,其中包含他们运行所需的一切。
通常情况下,Docker 容器是短暂的,运行的时间是需要在容器中发出的命令完成的时间。然而,有时,应用程序需要共享数据访问或在容器被删除后持续数据。 数据库、用户生成的网站内容和日志文件只是一些不切实际或不可能在Docker 图像中包含的数据的例子,但哪些应用程序需要访问。
Docker 卷可以用创建容器的相同命令创建和附加,也可以独立创建任何容器并稍后附加。
前提条件
要遵循这篇文章,你需要一个 Ubuntu 22.04 服务器,具有以下内容:
- 具有 sudo 特权的非 root 用户. 初始服务器设置与 Ubuntu 22.04指南解释了如何设置此设置。
- 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
在本示例中,您展示了如何使用数据量在两个容器之间共享数据,以及如何将数据量设置为只读。
结论
在本教程中,您创建了一个数据量,允许数据通过删除一个容器继续存在。您在容器之间共享数据量,并警告说应用程序需要设计以处理文件锁定以防止数据破坏。