小白快速上手 Docker 03 | Docker数据卷

数据卷

在前面使用Docker时,可能会遇到以下几个问题:

  1. 当Docker 里的容器挂了以后打不开,这时候只有删除该容器了,但删除容器会连容器中的产生的数据也一起删除了,大部分场景下这是不能接受的。
  2. Docker容器与容器之间不能直接交换数据。
  3. 容器和宿主机之间不能共享文件数据,如以nginx容器为例,需要修改默认页面内容时,需要先进入容器内部,再修改对应的index.html文件,极其不方便。

举个例子,假设我们的应用程序需要一个 MongoDB 数据库,因此,我们运行一个mongo容器:

docker run -d mongo

现在,如果容器被删除(无论是有意还是无意),我们将丢失 MongoDB 数据库中的所有数据。

这不是我们想要的。我们可能需要将数据持久地存储在数据库中,即使容器被删除了。

基于以上痛点,出现了容器数据卷的技术。

数据卷是宿主机中的一个目录或者文件,当容器目录挂载到宿主机的某个目录之后,宿主机的这个目录就成为了一个数据卷,这样容器和宿主机之间的文件就会同步。容器删除之后,容器产生的数据还会保留在宿主机上。这就解决了以上的问题。

数据卷类型

Docker 主要提供了两种不同的方式将数据从 Docker Host 挂载到 Docker 容器,来实现数据持久性:

  • 绑定挂载(Bind Mount)
  • 卷(Volumes)

Docker 卷主要有两种类型:

  • 匿名卷
  • 命名卷

中有三种数据卷类型:Bind Mount、匿名数据卷、命名数据卷,一般推荐大家使用 Bind Mount数据卷 方式持久化数据。

使用容器数据卷非常简单,只需在使用docker run命令运行容器的时候加上 -v 选项即可。

Bind Mount

bind mount自docker早期便开始为人们使用了,用于将host上的文件或目录被挂载到容器中。挂载时需要我们指定文件或目录在 host 上的完整路径。

docker run -d -v 主机目录:容器目录 镜像名称

通过这种方式运行命令后,会在宿主机上自动创建相应的目录,在宿主机上该目录下创建或者修改文件都会自动同步到容器中去。

下面通过Bind Mount形式启动一个nginx容器,并将宿主机目录/Users/qin/docker/volume/nginx_90映射到容器的/usr/share/nginx/html/目录。

进入到容器,查看/usr/share/nginx/html目录,发现容器内文件和宿主机内文件一致。

下面修改宿主机的index.html文件中v1改成v2,容器内对应的index.html文件内容也同步更改了:

删除容器后,数据卷还存在,这样保证了容器中相关数据的持久化。

需要注意的是:使用Bind Mount,宿主机文件夹将覆盖容器文件夹内容,因此如果宿主机文件夹为空,需要先将容器中要映射的文件复制到宿主机文件夹中。

Volumes

匿名数据卷

下面介绍如何通过匿名数据卷形式启动一个nginx容器,并将容器的/usr/share/nginx/html/目录映射到宿主机指定目录。

下面指令中的/usr/share/nginx/html是容器中的的路径,启动成功后docker 会将匿名卷映射到宿主机的某个途径,可以通过docker inspect查看到这个路径。

qin@linux-01:~$ docker run -itd -p 82:80  -v /usr/share/nginx/html  --name  nginx_82_anonymous_volume  nginx

匿名数据卷的优点在于,它们不需要用户手动管理。如果容器启动时使用了 --rm 选项,容器停止时,容器被自动删除,匿名卷也会自动被删除。(注意直接通过docker rm删除容器匿名卷不会被删除,只有通过docker stop停止容器才会将匿名卷删除)

但是如果容器启动时没有–rm选项,即使使用命名 docker stop/rm my_container 停止了容器,匿名卷不会被自动删除。

命名数据卷

与匿名卷相反,命名数据卷不会被附加到具体容器上,如果容器被删除,命名卷会保留。

qin@linux-01:~$ docker run -itd --rm -p 86:80  -v nginx_name_volume:/usr/share/nginx/html  --name  nginx_86_name_volume  nginx

此外需要注意的是不能在 Dockerfile 内创建命名卷,只能在运行容器时使用-v 选项指定。

卷和绑定挂载的读写权限

默认情况下,卷和绑定挂载都是可读写的,这意味着容器不仅可以读取主机上挂载的数据,还可以修改这些数据。

有时这可能不是我们所希望的,在某些情况下,你可能希望容器只具备读取权限,而不允许进行写入。

可以在 Docker 命令中的挂载选项后面添加:ro来指定挂载为只读。

例如,假设你有一个本地目录/path/to/local/html,你想把它挂载到容器内的/usr/share/nginx/html目录,并且希望这个挂载是只读的,你可以使用以下命令:

docker run -v /path/to/local/html:/usr/share/nginx/html:ro -d nginx

这条命令中的:ro确保了容器只能读取/usr/share/nginx/html中的内容,而不能修改它。

同样,如果你使用的是命名卷,你可以这样挂载:

docker run -v nginx-vol:/usr/share/nginx/html:ro -d nginx

多个容器间共享数据

另一个与持久性相关的问题是如何在多个容器之间共享文件/目录。

使用绑定挂载,容器只能在单个主机/机器内共享文件。

相比之下,使用卷可以实现更灵活的文件共享。通过卷,来自不同主机的容器可以共享底层数据。例如,可以使用 NFS(网络文件系统)或 S3(Amazon Simple Storage Service)等解决方案,让多个主机上此类的容器访问同一份数据。

案例

最后让我们看看如何使用绑定挂载和卷解决我们之前讨论过的 MongoDB 持久性问题。

要使用绑定挂载,我们需要指定宿主机的路径(/path/on/your/host)映射到容器内的/data/db目录。

docker run -v /path/on/your/host:/data/db -d mongo

使用匿名卷则不需要指定宿主机的路径:

docker run -v /data/db -d mongo

第一次运行时,Docker 会自动创建一个具有随机名称的新卷。

使用命名卷需要指定卷的名称,在本例中卷的名称指定为mongo_data

docker run -v mongo_data:/data/db -d mongo

如果指定名称的卷在本地不存在,则会自动创建。

数据卷相关命令

docker提供了一系列命令用于Docker数据卷管理,这些命令都是以docker volume开头,理解和熟练运用这些命令,将有助于我们高效地管理容器数据,确保数据的持久性和一致性。

#查看系统中有哪些数据卷
docker volume  ls


#删除指定的一个或者多个数据卷
docker volume  rm 数据卷名

#docker volume prune 命令删除所有没有被挂载到容器的数据卷,不管该数据卷是具名的还是匿名的。
docker volume prune

#查看指定数据卷的信息 
docker volume inspect 数据卷名

#创建一个数据卷,该数据卷并没有挂载到任何容器
docker volume create 数据卷名
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值