docker的volumes理解

2,376 阅读4分钟

docker的run命令中的 "-v"参数的作用

# docker run --help | grep volume
  -v, --volume list                    Bind mount a volume
      --volume-driver string           Optional volume driver for the container
      --volumes-from list              Mount volumes from the specified container(s)

那么Dockerfile中的VOLUME指令实际使用中是不是就是跟docker run中的-v参数一样是将宿主机的一个目录绑定到容器中的目录以达到共享目录的作用呢?并不然,其实VOLUME指令只是起到了声明了容器中的目录作为匿名卷,但是并没有将匿名卷绑定到宿主机指定目录的功能。但是当我们生成镜像的Dockerfile中以Volume声明了匿名卷,并且我们以这个镜像run了一个容器的时候,docker会在安装目录下的指定目录下面生成一个目录来绑定容器的匿名卷(这个指定目录不同版本的docker会有所不同)。如我使用的版本如下:

[root@DEV-BD-DOC ~]# docker --version
Docker version 19.03.1, build 74b1e89    //docker版本
[root@DEV-BD-DOC volumes]# pwd
/var/lib/docker/volumes          //默认绑定容器的匿名卷的目录
[root@DEV-BD-DOC volumes]# ll
total 24
drwxr-xr-x 3 root root    19 Oct 24 15:32 1c690d47cb034a4354b20875c2d9e2042471f1498649ab2623f3efe97789c449   //若没有相应的容器,则该目录下只有 metadata.db
drwxr-xr-x 3 root root    19 Oct 24 11:45 81f8740bcb9e64c097580b9f20ec02e0e50f494dd516b7d048f0dcfd78d42406
-rw------- 1 root root 32768 Oct 24 15:32 metadata.db

就是说当Dockerfile中声明了匿名卷但是run的时候没有使用 -v绑定匿名卷的话那么docker就会在/var/lib/docker/volumes这个目录下创建一个目录来绑定匿名卷。 所以真正使用的时候我们在Dockerfile构建镜像的时候如:

FROM centos:latest
RUN groupadd -r redis && useradd  -r -g redis redis
RUN yum -y update &&  yum -y install epel-release && yum -y install redis && yum -y install net-tools

RUN mkdir -p /config && chown -R redis:redis /config

VOLUME /share/data      #声明容器中/share/data为匿名卷

EXPOSE 6379

那么使用该Dockerfile构建镜像的为

# docker build -t image-redis    //构建镜像image-redis
......
#docker run -itd -name redis1 -v /data:/share/data image-redis    //运行一个容器并且将当前机器的/data目录绑定到容器的匿名卷中
.....
#docker run -itd  -name redis2 image-redis     //运行一个容器但是不绑定目录到容器的匿名卷,这时候再/var/lib/docker/volumes(不同版本目录不一样)中就会创建一个目录绑定匿名卷
.....

参考1 参考2 官网参考

VOLUME /opt 是把 docker 容器中/opt的文件拷贝到docker指定的宿主机的 /var/lib/docker/volumes/(默认该目录) ,docker inspect

        "Mounts": [
            {
                "Type": "volume",
                "Name": "1c690d47cb034a4354b20875c2d9e2042471f1498649ab2623f3efe97789c449",
                "Source": "/var/lib/docker/volumes/1c690d47cb034a4354b20875c2d9e2042471f1498649ab2623f3efe97789c449/_data",
                "Destination": "/opt",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

这里描述了目录,跟 docker run 的 -v 参数 不指定宿主机目录的效果是一样的

docker run -it --name container-test -h CONTAINER -v /data debian /bin/bash

docker run -v参数是有三个字段,第一个是宿主机目录,第二个是容器目录,最后是读写

$ docker run -d \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html:ro \
  nginx:latest

docker 创建镜像后,在Dockerfile中有VOLUME 但不会在默认volumes中创建数据 _data 层,但执行docker run 之后,就会出现对应的数据目录,默认可读写

在对应的 _data 目录中创建文件

echo '666' > new

在容器中查看 /opt 目录

root@32579fc5f1de:/opt# ls
new  yimicmdb_backend
root@32579fc5f1de:/opt# cat new 
666