docker基础知识之挂载本地目录的方法 您所在的位置:网站首页 挂载点没有docker docker基础知识之挂载本地目录的方法

docker基础知识之挂载本地目录的方法

2024-01-03 02:40| 来源: 网络整理| 查看: 265

Docker可以支持把一个宿主机上的目录挂载到镜像里。docker run -it -v /home/dock/Downloads:/usr/Downloads ubuntu64 /bin/bash通过-v参数,冒号前为宿主机目录,必须为绝对路径,冒号后为镜像内挂载的路径。 2017041809263615.png现在镜像内就可以共享宿主机里的文件了。默认挂载的路径权限为读写。如果指定为只读可以用:rodocker run -it -v /home/dock/Downloads:/usr/Downloads:ro ubuntu64 /bin/bashdocker还提供了一种高级的用法。叫数据卷。数据卷:“其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的”。感觉像是由一个容器定义的一个数据挂载信息。其他的容器启动可以直接挂载数据卷容器中定义的挂载信息。看示例:docker run -v /home/dock/Downloads:/usr/Downloads  --name dataVol ubuntu64 /bin/bash创建一个普通的容器。用--name给他指定了一个名(不指定的话会生成一个随机的名子)。再创建一个新的容器,来使用这个数据卷。docker run -it --volumes-from dataVol ubuntu64 /bin/bash2017041809263716.png--volumes-from用来指定要从哪个数据卷来挂载数据。 如何在Docker容器内外互相拷贝数据?从容器内拷贝文件到主机上docker cp :/file/path/within/container /host/path/target  从主机上拷贝文件到容器内1.用-v挂载主机数据卷到容器内docker run -v /path/to/hostdir:/mnt $container 在容器内拷贝  cp /mnt/sourcefile /path/to/destfile 2.直接在主机上拷贝到容器物理存储系统 A. 获取容器名称或者id :$ docker ps B. 获取整个容器的id$ docker inspect -f  '``.`Id`' 步骤A获取的名称或者id C. 在主机上拷贝文件:$ sudo cp path-file-host /var/lib/docker/aufs/mnt/FULL_CONTAINER_ID/PATH-NEW-FILE   或者  $ sudo cp path-file-host /var/lib/docker/devicemapper/mnt/123abc/rootfs/root  例子:$ docker ps  CONTAINER ID   IMAGE  COMMAND    CREATED   STATUS    PORTS    NAMES  d8e703d7e303  solidleon/ssh:latest   /usr/sbin/sshd -D           cranky_pare  $ docker inspect -f  '``.`Id`' cranky_pare or   $ docker inspect -f  '``.`Id`' d8e703d7e303  d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5  $ sudo cp file.txt /var/lib/docker/aufs/mnt/**d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5 3.用输入输出符docker run -i ubuntu /bin/bash -c 'cat > /path/to/container/file' < /path/to/host/file/  或者docker exec -it bash -c 'cat > /path/to/container/file' < /path/to/host/file/  

Docker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定。 譬如我要启动一个CentOS容器,宿主机的/test目录挂载到容器的/soft目录,可通过以下方式指定: # docker run -it -v /test:/soft centos /bin/bash 这样在容器启动后,容器内会自动创建/soft的目录。通过这种方式,我们可以明确一点,即-v参数中,冒号":"前面的目录是宿主机目录,后面的目录是容器内目录。 貌似简单,其实不然,下面我们来验证一下: 一、容器目录不可以为相对路径 [root@localhost ~]# docker run -it -v /test:soft centos /bin/bash invalid value "/test:soft" for flag -v: soft is not an absolute path See 'docker run --help'. 直接报错,提示soft不是一个绝对路径,所谓的绝对路径,必须以下斜线“/”开头。 二、宿主机目录如果不存在,则会自动生成 如果宿主机中存在/test目录,首先删除它 [root@localhost ~]# rm -rf /test [root@localhost ~]# ls / bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var 启动容器 [root@localhost ~]# docker run -it -v /test:/soft centos /bin/bash [root@a487a3ca7997 /]# ls bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  soft  srv  sys  tmp  usr  var 查看宿主机,发现新增了一个/test目录 [root@localhost ~]# ls / bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  test  tmp  usr  var 三、宿主机的目录如果为相对路径呢? 这次,我们换个目录名test1试试 # docker run -it -v test1:/soft centos /bin/bash 再到宿主机上查看是否新增了一个/test1目录,结果没有,是不是因为我用的是相对路径,所以生成的test1目录在当前目录下,结果发现还是没有。那容器内的/soft目录挂载到哪里去了?通过docker inspect命令,查看容器“Mounts”那一部分,我们可以得到这个问题的答案。     "Mounts": [         {             "Name": "test1",             "Source": "/var/lib/docker/volumes/test1/_data",             "Destination": "/soft",             "Driver": "local",             "Mode": "z",             "RW": true         }     ], 可以看出,容器内的/soft目录挂载的是宿主机上的/var/lib/docker/volumes/test1/_data目录 原来,所谓的相对路径指的是/var/lib/docker/volumes/,与宿主机的当前目录无关。 四、如果只是-v指定一个目录,这个又是如何对应呢? 启动一个容器 [root@localhost ~]# docker run -it -v /test2 centos /bin/bash [root@ea24067bc902 /]# ls bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  test2  tmp  usr  var 同样使用docker inspect命令查看宿主机的挂载目录   "Mounts": [         {             "Name": "96256232eb74edb139d652746f0fe426e57fbacdf73376963e3acdb411b3d73a",             "Source": "/var/lib/docker/volumes/96256232eb74edb139d652746f0fe426e57fbacdf73376963e3acdb411b3d73a/_data",             "Destination": "/test2",             "Driver": "local",             "Mode": "",             "RW": true         }     ], 可以看出,同3中的结果类似,只不过,它不是相对路径的目录名,而是随机生成的一个目录名。 五、如果在容器内修改了目录的属主和属组,那么对应的挂载点是否会修改呢? 首先开启一个容器,查看容器内/soft目录的属性 [root@localhost ~]# docker run -it -v /test:/soft centos /bin/bash [root@b5ed8216401f /]# ll -d /soft/ drwxr-xr-x 2 root root 6 Sep 24 03:48 /soft/ 查看宿主机内/test目录的属性 [root@localhost ~]# ll -d /test/ drwxr-xr-x 2 root root 6 Sep 24 11:48 /test/ 在容器内新建用户,修改/soft的属主和属组 [root@b5ed8216401f /]# useradd victor [root@b5ed8216401f /]# chown -R victor.victor /soft/ [root@b5ed8216401f /]# ll -d /soft/ drwxr-xr-x 2 victor victor 6 Sep 24 03:48 /soft/ 再来看看宿主机内/test目录的属主和属组是否会发生变化? [root@localhost ~]# ll -d /test/ drwxr-xr-x 2 mycat mycat 6 Sep 24 11:48 /test/ 竟然变为mycat了。。。原来,这个与UID有关系,UID,即“用户标识号”,是一个整数,系统内部用它来标识用户。一般情况下它与用户名是一一对应的。 首先查看容器内victor对应的UID是多少, [root@b5ed8216401f /]# cat /etc/passwd | grep victor victor:x:1000:1000::/home/victor:/bin/bash victor的UID为1000,那么宿主机内1000对应的用户是谁呢? [root@localhost ~]# cat /etc/passwd |grep 1000 mycat:x:1000:1000::/home/mycat:/bin/bash 可以看出,宿主机内UID 1000对应的用户是mycat。 六、容器销毁了,在宿主机上新建的挂载目录是否会消失? 在这里,主要验证两种情况: 一、指定了宿主机目录,即 -v /test:/soft。 二、没有指定宿主机目录,即-v /soft 第一种情况: [root@localhost ~]# rm -rf /test    --首先删除宿主机的/test目录 [root@localhost ~]# ls /    --可以看到,宿主机上无/test目录 bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var [root@localhost ~]# docker run -it --name=centos_test -v /test:/soft centos /bin/bash  --启动容器,为了删除方便,我用--name参数指定了容器的名字 [root@82ad7f3a779a /]# exit exit [root@localhost ~]# docker rm centos_test  --删除容器 centos_test [root@localhost ~]# ls /  --发现 /test目录依旧存在 bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  test  tmp  usr  var 可以看出,即便容器销毁了,新建的挂载目录不会消失。进一步也可验证,如果宿主机目录的属主和属组发生了变化,容器销毁后,宿主机目录的属主和属组不会恢复到挂载之前的状态。 第二种情况,通过上面的验证知道,如果没有指定宿主机的目录,则容器会在/var/lib/docker/volumes/随机配置一个目录,那么我们看看这种情况下的容器销毁是否会导致相应目录的删除 首先启动容器 [root@localhost ~]# docker run -it --name=centos_test -v /soft centos /bin/bash [root@6b75579ec934 /]# exit exit 通过docker inspect命令查看容器在宿主机上生成的挂载目录     "Mounts": [         {             "Name": "b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301",             "Source": "/var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301/_data",             "Destination": "/soft",             "Driver": "local",             "Mode": "",             "RW": true         }     ],   对应的是/var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301/_data目录 销毁容器,看目录是否存在 [root@localhost ~]# docker rm centos_test centos_test [root@localhost ~]# ll /var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301 total 0 drwxr-xr-x 2 root root 6 Sep 24 14:25 _data发现该目录依旧存在,即便重启了docker服务,该目录依旧存在 [root@localhost ~]# systemctl restart docker [root@localhost ~]# ll /var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301 total 0 drwxr-xr-x 2 root root 6 Sep 24 14:25 _data 七、挂载宿主机已存在目录后,在容器内对其进行操作,报“Permission denied”。 可通过两种方式解决: 1> 关闭selinux。 临时关闭:# setenforce 0 永久关闭:修改/etc/sysconfig/selinux文件,将SELINUX的值设置为disabled。 2> 以特权方式启动容器 指定--privileged参数 如:# docker run -it --privileged -v /test:/soft centos /bin/bash 一、通过docker run命令 1、运行命令:docker run --name test -it -v /home/xqh/myimage:/data ubuntu  /bin/bash 其中的 -v 标记 在容器中设置了一个挂载点 /data(就是容器中的一个目录),并将主机上的 /home/xqh/myimage 目录中的内容关联到 /data下。 这样在容器中对/data目录下的操作,还是在主机上对/home/xqh/myimage的操作,都是完全实时同步的,因为这两个目录实际都是指向主机目录。 2、运行命令:docker run --name test1 -it -v /data ubuntu /bin/bash 上面-v的标记只设置了容器的挂载点,并没有指定关联的主机目录。这时docker会自动绑定主机上的一个目录。通过docker inspect 命令可以查看到。 xqh@ubuntu:~/myimage$ docker inspect test1 [ {     "Id": "1fd6c2c4bc545163d8c5c5b02d60052ea41900a781a82c20a8f02059cb82c30c", .............................     "Mounts": [         {             "Name": "0ab0aaf0d6ef391cb68b72bd8c43216a8f8ae9205f0ae941ef16ebe32dc9fc01",             "Source": "/var/lib/docker/volumes/0ab0aaf0d6ef391cb68b72bd8c43216a8f8ae9205f0ae941ef16ebe32dc9fc01/_data",             "Destination": "/data",             "Driver": "local",             "Mode": "",             "RW": true         }     ], ........................... 上面 Mounts下的每条信息记录了容器上一个挂载点的信息,"Destination" 值是容器的挂载点,"Source"值是对应的主机目录。 可以看出这种方式对应的主机目录是自动创建的,其目的不是让在主机上修改,而是让多个容器共享。  二、通过dockerfile创建挂载点 上面介绍的通过docker run命令的-v标识创建的挂载点只能对创建的容器有效。 通过dockerfile的 VOLUME 指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点。 还有一个区别是,通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。 #test FROM ubuntu MAINTAINER hello1 VOLUME ["/data1","/data2"] 上面的dockfile文件通过VOLUME指令指定了两个挂载点 /data1 和 /data2. 我们通过docker inspect 查看通过该dockerfile创建的镜像生成的容器,可以看到如下信息     "Mounts": [         {             "Name": "d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21",             "Source": "/var/lib/docker/volumes/d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21/_data",             "Destination": "/data1",             "Driver": "local",             "Mode": "",             "RW": true         },         {             "Name": "6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36",             "Source": "/var/lib/docker/volumes/6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36/_data",             "Destination": "/data2",             "Driver": "local",             "Mode": "",             "RW": true         }     ], 可以看到两个挂载点的信息。 三、容器共享卷(挂载点) docker run --name test1 -it myimage /bin/bash 上面命令中的 myimage是用前面的dockerfile文件构建的镜像。 这样容器test1就有了 /data1 和 /data2两个挂载点。 下面我们创建另一个容器可以和test1共享 /data1 和 /data2卷 ,这是在 docker run中使用 --volumes-from标记,如: 可以是来源不同镜像,如: docker run --name test2 -it --volumes-from test1  ubuntu  /bin/bash 也可以是同一镜像,如: docker run --name test3 -it --volumes-from test1  myimage  /bin/bash 上面的三个容器 test1 , test2 , test3 均有 /data1 和 /data2 两个目录,且目录中内容是共享的,任何一个容器修改了内容,别的容器都能获取到。 四、最佳实践:数据容器 如果多个容器需要共享数据(如持久化数据库、配置文件或者数据文件等),可以考虑创建一个特定的数据容器,该容器有1个或多个卷。 其它容器通过--volumes-from 来共享这个数据容器的卷。因为容器的卷本质上对应主机上的目录,所以这个数据容器也不需要启动。 如: docker run --name dbdata myimage echo "data container"



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有