Docker中的数据挂载

一、概念

引用

  • Docker 镜像时由多个文件系统(只读层)叠加而成。当我们启动一个容器的时候,Docker会加载只读镜像层并在其上添加一个读写曾。如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在并未改变(这可能就是Docker说的copy on wirte),只是被读写层中的副本隐藏掉了,当删除容器,再通过同一个镜像再次启动的时候,之前的修改就丢失了,在Docker中,只读层及在顶部的读写层的组合被成为UnionFile System(UFS联合文件系统)
  • Docker中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker中称为数据卷(Data Volume)。数据卷可以用来存储Docker应用的数据,亦可以用来在Docker容器间共享数据。数据呈现给Docker容器的形式就是一个目录,支持多个容器间共享,修改也不会影响镜像。使用DOcker数据卷,类似在系统中使用mount挂载一个文件系统。
  • 为了能够保存数据或者容器间共享数据,Docker提出了Volume概念,简单来说,Volume就是目录或者文件,它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。

二、创建数据卷

  • 方式一:使用命令创建
# 事先创建一个名为myVolume的数据卷,该数据卷会保存在宿主机/var/lib/docker/volumes目录下
docker volume create myVolume
# 在创建容器的时候可以指定使用该数据卷,并绑定到容器中指定的目录
docker run -it -v myVolume:/ab -p 9898:80 --name mynginx nginx:latest /bin/bash

# 或者直接在启动容器的时候创建数据卷,不用事先准备,也不会报错
docker run -it -v hisVolume:/ab -p 9898:80 --name mynginx nginx:latest /bin/bash
  • 方式二:使用默认数据卷
    上面的方式是先创建,再使用,我们可以不实现准备好,使用默认的。
# 直接 -v /ab 就是,容器中的/ab目录挂载到宿主机的匿名数据卷中
[ech@centos-10 _data]$ docker run -it -v /ab -p 9898:80 --name mynginx nginx:latest /bin/bash
# 进入该目录
root@98c7ed71827c:/# cd /ab
# 添加一个文件
root@98c7ed71827c:/ab# echo "hello volume!" > hello.txt
# 退出
root@98c7ed71827c:/ab# exit
exit
# 查看该容器对应默认数据卷在哪
[ech@centos-10 _data]$ docker inspect mynginx | grep /var/lib/docker/volumes/
                "Source": "/var/lib/docker/volumes/2c6723ead7638ff16ca6b2625871480f57ad7815c84b086c46dd0c132dcb23b9/_data",
# 进入该目录
[ech@centos-10 _data]$ cd /var/lib/docker/volumes/2c6723ead7638ff16ca6b2625871480f57ad7815c84b086c46dd0c132dcb23b9/_data
# 在容器中创建的文件在宿主机中找到了
[ech@centos-10 _data]$ ls
hello.txt
[ech@centos-10 _data]$ cat hello.txt 
hello volume!

三、挂载宿主机文件(夹)到容器

这就相当于是一个文件映射,将宿主机的文件映射到容器中,可以在docker run 的时候通过-v命令来指定

# 将本机opt目录映射到容器中的opt目录,这样以来,在容器中对opt目录下的操作都会反映到宿主机上
docker run -it -v /opt:/opt --name nginx:latest mynginx /bin/bash
# 给文件设置权限,ro = readonly
docker run -it -v /opt:/opt:ro --name nginx:latest mynginx /bin/bash
# 可以通过多个-v来同时挂载多个文件
docker run -it -v /opt:/opt:ro -v /a:/a:ro --name nginx:latest mynginx /bin/bash

注意:如果指定的宿主机目录不存在或者容器中的路径不存在都会被docker直接创建

四、在Dockerfile中配置挂载

由于Dockerfile可能运行在各种系统中,如果像docker run中使用-v指令那样配置volume,可能会出问题,例如linux和windows的路径就不一样。所以在Dockerfile只能声明匿名挂载卷,并在Dockerfile中声明的挂载卷会被应用在使用该Dockerfile的各个容器上,注意,虽然用的是一个Dockerfile但是各个容器实例在宿主机上的挂载卷可不一样!!

FROM ubuntu
# 这就相当于是 docker run -v /data1 -v /data2,创建匿名数据卷
VOLUME ["/data1","/data2"]

Q.E.D.