在Docker的使用过程中往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,所以这就涉及到Docker容器的数据操作。
容器中数据管理主要有两种方式:数据卷和数据卷容器。

  1. 数据卷(Data Volumes) 容器内数据直接映射到本地宿主机。
  2. 数据卷容器(Data Volume Containers) 使用特定容器维护数据卷。

数据卷

数据卷是一个特殊的目录,它将主机目录直接映射进容器。可供一个或多个容器使用。

数据卷设计的目的就是为了 数据的持久化,它完全独立与容器的生命周期。因此,容器删除时,不会删除其挂载的数据卷,也不会存在类似的垃圾机制对容器存在的数据卷进行处理。

数据卷的特性:

  • 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷中
  • 数据卷可以在容器之间共享和重用
  • 可以对数据卷里的内容直接修改,修改回马上生效,无论是容器内操作还是本地操作
  • 对数据卷的更新不会影响镜像的更新
  • 数据卷会一直存在,即使挂载数据卷的容器已经被删除

在容器中创建一个数据卷
使用的命令如:

[root@localhost ~]# docker run -v /root/datavolume:/data -it hub.c.163.com/library/ubuntu /bin/bash

其中-v,表示在容器中创建一个数据卷。
/root/datavolume:/data,表示主机的目录/root/datavolume映射到容器中的/data目录。
示例:

[root@localhost ~]# docker run -v /root/datavolume:/data -it hub.c.163.com/library/ubuntu /bin/bash
root@c863c5094922:/# ll
total 24
drwxr-xr-x.  22 root root 4096 Mar 24 02:30 ./
drwxr-xr-x.  22 root root 4096 Mar 24 02:30 ../
-rwxr-xr-x.   1 root root    0 Mar 24 02:30 .dockerenv*
drwxr-xr-x.   2 root root 4096 Jan 19 16:33 bin/
drwxr-xr-x.   2 root root    6 Apr 12  2016 boot/
drwxr-xr-x.   2 root root   15 Mar 22 11:30 data/
drwxr-xr-x.   5 root root  380 Mar 24 02:30 dev/
drwxr-xr-x.  42 root root 4096 Mar 24 02:30 etc/
drwxr-xr-x.   2 root root    6 Apr 12  2016 home/
drwxr-xr-x.   8 root root   90 Sep 13  2015 lib/
drwxr-xr-x.   2 root root   33 Jan 19 16:32 lib64/
drwxr-xr-x.   2 root root    6 Jan 19 16:31 media/
drwxr-xr-x.   2 root root    6 Jan 19 16:31 mnt/
drwxr-xr-x.   2 root root    6 Jan 19 16:31 opt/
dr-xr-xr-x. 223 root root    0 Mar 24 02:30 proc/
drwx------.   2 root root   35 Jan 19 16:33 root/
drwxr-xr-x.   6 root root   68 Mar 24 02:30 run/
drwxr-xr-x.   2 root root 4096 Jan 20 21:43 sbin/
drwxr-xr-x.   2 root root    6 Jan 19 16:31 srv/
dr-xr-xr-x.  13 root root    0 Mar  3 18:56 sys/
drwxrwxrwt.   2 root root    6 Jan 19 16:33 tmp/
drwxr-xr-x.  10 root root   97 Jan 20 21:43 usr/
drwxr-xr-x.  11 root root 4096 Jan 20 21:43 var
root@c863c5094922:/# [root@localhost ~]# 
[root@localhost ~]# ll
总用量 4
-rw-------. 1 root root 1209 34 02:52 anaconda-ks.cfg
drwxr-xr-x. 3 root root   39 323 13:51 backup
drwxr-xr-x. 2 root root   15 322 19:30 datavolume
drwxr-xr-x. 4 root root   34 323 10:01 dockerfile
[root@localhost ~]# pwd
/root
[root@localhost ~]# 

下面使用touch命令创建一个文件vo_file1

root@c863c5094922:/data# touch vo_file1
root@c863c5094922:/data# ls -l
-rw-r--r--. 1 root root  0 Mar 24 02:49 vo_file1
root@c863c5094922:/data# 

如果出现类似与权限的问题,如:
touch: cannot touch xxxx': Permission denied
可以使用
su -c “setenforce 0”`
下面在文件中写点内容,测试下,容器和主机是否同步。

root@c863c5094922:/data# echo "this is a test datavolume" > vo_file1 
root@c863c5094922:/data# cat vo_file1 
this is a test datavolume
root@c863c5094922:/data# [root@localhost datavolume]# 
[root@localhost datavolume]# cat /root/datavolume/vo_file1 
this is a test datavolume
[root@localhost datavolume]# 

可以看到容器中的vo_file1和宿主机中的vo_file1内容一样。
使用docker inspect 容器id/容器名可以查看具体信息,其中mounts的具体信息如下:

[root@localhost datavolume]# docker inspect c863c5094922
"Mounts": [
            {
                "Source": "/root/datavolume",
                "Destination": "/data",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],

Docker挂载数据卷的默认权限是读写(rw),通过上面的 “RW”: true可以看到,我们也可以在创建的时候进行设置为只读,使用ro

docker run -v /root/datavolume:/data:ro -it hub.c.163.com/library/ubuntu /bin/bash

示例:

root@localhost datavolume]# docker run -v /root/datavolume:/data:ro -it hub.c.163.com/library/ubuntu /bin/bash
root@2a8706e63796:/# touch /data/vo_file2
touch: cannot touch '/data/vo_file2': Read-only file system

通过docker inspect可以查看容器的信息:

"Mounts": [
            {
                "Source": "/root/datavolume",
                "Destination": "/data",
                "Mode": "ro",
                "RW": false,
                "Propagation": "rprivate"
            }
        ],

这里”RW”就为false.
使用Dockerfile构建包含数据卷的镜像:
我创建了一个Dockerfile,如下:

[root@localhost vo_test]# cat Dockerfile 
FROM hub.c.163.com/library/ubuntu
VOLUME ["/datavolume1","/dockervolume2"]
CMD /bin/bash
[root@localhost vo_test]# pwd
/root/dockerfile/vo_test
[root@localhost vo_test]# 

下面构建镜像:

[root@localhost vo_test]# docker build -t df_vo .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM hub.c.163.com/library/ubuntu
 ---> f49eec89601e
Step 2 : VOLUME /datavolume1 /dockervolume2
 ---> Running in 39ce6de3a943
 ---> 4921812de13d
Removing intermediate container 39ce6de3a943
Step 3 : CMD /bin/bash
 ---> Running in f9afdbaf2471
 ---> 2ee7e110e18d
Removing intermediate container f9afdbaf2471
Successfully built 2ee7e110e18d
[root@localhost vo_test]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
df_vo                          latest              2ee7e110e18d        6 seconds ago       129.5 MB

下面利用这个镜像创建容器votest1:

[root@localhost vo_test]# docker run --name votest1 -it df_vo
root@a98bbf9dbfae:/# ls
bin  boot  datavolume1  dev  dockervolume2  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@a98bbf9dbfae:/# 

可以看到这个容器中已经包含了datavolume1和datavolume2两个数据卷。
再使用这个镜像运行一个容器votest2:

[root@localhost _data]# docker run --name votest2 -it df_vo
root@9501be4f50d4:/# 
root@9501be4f50d4:/# ls
bin  boot  datavolume1  dev  dockervolume2  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@9501be4f50d4:/# [root@localhost _data]#

通过docker inspect 分别查看这两个容器的信息。可以发现两个容器内数据卷对应到主机的地址(docker自己创建的)并不一样
如下:
votest1的容器信息:

[root@localhost vo_test]# docker inspect votest1
"Mounts": [
            {
                "Name": "4ae9914bc4bd127e669b89ee6b703a0c9cc91f18c8dfe5034dbb838de2ca8062",
                "Source": "/var/lib/docker/volumes/4ae9914bc4bd127e669b89ee6b703a0c9cc91f18c8dfe5034dbb838de2ca8062/_data",
                "Destination": "/datavolume1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Name": "753a10fd08491a41aa953427a4cf7b30276604175b8e237cfea2aed0ddbeaf48",
                "Source": "/var/lib/docker/volumes/753a10fd08491a41aa953427a4cf7b30276604175b8e237cfea2aed0ddbeaf48/_data",
                "Destination": "/dockervolume2",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

votest2的容器信息:

[root@localhost _data]# docker inspect votest2
"Mounts": [
            {
                "Name": "a455e9d38eb656375316c0a96ec0dd69d900f3477d39752a417dac725d8b6854",
                "Source": "/var/lib/docker/volumes/a455e9d38eb656375316c0a96ec0dd69d900f3477d39752a417dac725d8b6854/_data",
                "Destination": "/dockervolume2",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Name": "449d3f7c271d0f6ab8f3cd7df0fc4f79510ebeeee888b65283db58c77031d66c",
                "Source": "/var/lib/docker/volumes/449d3f7c271d0f6ab8f3cd7df0fc4f79510ebeeee888b65283db58c77031d66c/_data",
                "Destination": "/datavolume1",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],

对应的主机数据卷位置:

 [root@localhost _data]# cd /var/lib/docker/volumes/
[root@localhost volumes]# ll
总用量 32
drwxr-xr-x. 3 root root    18 37 11:48 122d96164df0f84b6132c67cb7db1368b67df81420b03c48ccd0bce682241e4b
drwxr-xr-x. 3 root root    18 37 09:46 174a0ebf6f790834a04d7dda48b1e24702e9a98f805c0c6331aa49e294736143
drwxr-xr-x. 3 root root    18 37 09:47 335c944921f8ec1f4d96fe8a0a15802f69f591549461710fea4bc9c92cd13018
drwxr-xr-x. 3 root root    18 37 10:03 3893ab8ce0aca2128bd3847488f57431285a943ded814843f1aaf993e64b902e
drwxr-xr-x. 3 root root    18 324 11:53 449d3f7c271d0f6ab8f3cd7df0fc4f79510ebeeee888b65283db58c77031d66c
drwxr-xr-x. 3 root root    18 324 11:48 4ae9914bc4bd127e669b89ee6b703a0c9cc91f18c8dfe5034dbb838de2ca8062
drwxr-xr-x. 3 root root    18 323 10:12 6cd6a34adf1fe157cf813a0016011966f97c866874ad10137728ebf824b76e01
drwxr-xr-x. 3 root root    18 324 11:48 753a10fd08491a41aa953427a4cf7b30276604175b8e237cfea2aed0ddbeaf48
drwxr-xr-x. 3 root root    18 322 20:02 7764cd58f82d0d782e97c9b719825c42dc34806ae995257f0082342396b4a630
drwxr-xr-x. 3 root root    18 324 11:53 a455e9d38eb656375316c0a96ec0dd69d900f3477d39752a417dac725d8b6854
drwxr-xr-x. 3 root root    18 37 10:07 a4af7ebbb3da863176fe4db6234d9e69b2e47ce628b0f3770854ed75c40e3604
drwxr-xr-x. 3 root root    18 322 20:02 abecf3deb59ded6262a20ddc94f0e6505ea3dd1c717260594fa4a8b0260c136c
drwxr-xr-x. 3 root root    18 36 15:27 db6529f59f1ceb789047f7c340951c48c463c840e74974d7cfd04d7fad2a3468
drwxr-xr-x. 3 root root    18 37 09:58 e33c562f6e4beb2711ba50cb188ba51faf670b2aa56e571749fc96ce876c0d5c
drwxr-xr-x. 3 root root    18 323 10:12 e82ea714065869185dad3e50703ed44f877794a0a201143679c4b40dc2af4a4d
-rw-------. 1 root root 65536 324 11:53 metadata.db
[root@localhost volumes]# 

数据卷容器
用户需要在多个容器之间共享一些数据,就可以使用数据卷容器。

命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器,就叫数据卷容器。

1.先创建一个容器
2.然后挂载。
挂载数据卷容器的方法:

docker run --volumes-from 容器名

示例:

首先创建一个容器votest3:

[root@localhost volumes]# docker run --name votest3 -it df_vo
root@c31f85a96a68:/# ls
bin  boot  datavolume1  dev  dockervolume2  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@c31f85a96a68:/#

可以看到里面有数据卷datavolume1和dockervolume2,然后在datavolume1中创建一个文件vo_file:

root@c31f85a96a68:/# touch datavolume1/vo_file
root@c31f85a96a68:/# ls datavolume1/
vo_file

然后再创建一个容器votest4挂载votest3,可以看到里面也包含同样的数据卷,然后在datavolume1中创建文件vo_file1:

[root@localhost volumes]# docker run -it --name votest4 --volumes-from votest3 hub.c.163.com/library/ubuntu /bin/bash
root@917fc6a610df:/# ls
bin  boot  datavolume1  dev  dockervolume2  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@917fc6a610df:/# ls datavolume1/
vo_file
root@917fc6a610df:/# touch datavolume1/vo_file1 
root@917fc6a610df:/# ls datavolume1/       
vo_file  vo_file1

同样我们再创建一个容器votest5,然后在datavolume中创建文件vo_file2

[root@localhost volumes]# docker run -it --name votest5 --volumes-from votest3 hub.c.163.com/library/ubuntu /bin/bash
root@61eb42648402:/# ls
bin  boot  datavolume1  dev  dockervolume2  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@61eb42648402:/# ls datavolume1/
vo_file  vo_file1
root@61eb42648402:/# touch datavolume1/vo_file2 
root@61eb42648402:/# ls datavolume1/
vo_file  vo_file1  vo_file2
root@61eb42648402:/#

我们连接分别连接vo_test3和vo_test4查看里面的文件:

[root@localhost volumes]# docker attach votest3
root@c31f85a96a68:/# 
root@c31f85a96a68:/# ls datavolume1/
vo_file  vo_file1  vo_file2
root@c31f85a96a68:/# 
[root@localhost volumes]# docker attach votest4
root@917fc6a610df:/# 
root@917fc6a610df:/# ls datavolume1/
vo_file  vo_file1  vo_file2
root@917fc6a610df:/# 

可以看到数据进行了同步。
如果我们删除votest3,可以发现数据卷并没有被删除。

[root@localhost volumes]# docker rm votest3
votest3
[root@localhost volumes]# docker attach votest4
root@917fc6a610df:/# 
root@917fc6a610df:/# ls datavolume1/
vo_file  vo_file1  vo_file2
root@917fc6a610df:/# 

数据卷的备份和还原
数据卷备份使用的命令:

docker run --volumes-from 存在的容器名 -v $(pwd):/backup --name 新建的容器名 镜像名 tar cvf /backup/backup.tar 数据卷

$(pwd)当前路径

示例(使用之前创建的votest5):

[root@localhost volumes]# docker run --volumes-from votest5 -v /root/backup:/backup hub.c.163.com/library/ubuntu tar cvf /backup/vof.tar /datavolume1
tar: Removing leading `/' from member names
/datavolume1/
/datavolume1/vo_file
/datavolume1/vo_file1
/datavolume1/vo_file2
[root@localhost volumes]# ls /root/backup/
vof.tar
[root@localhost volumes]# 

可以看到已经备份到/root/backup/下。

数据卷的还原:

使用命令类似:

docker run --volumes-from 存在的容器名 -v $(pwd):/backup --name 新建的容器名 镜像名 tar xvf /backup/backup.tar

示例:
创建一个容器votest8还原数据卷

[root@localhost backup]# docker run --volumes-from votest5 -v /root/backup:/backup --name votest8 hub.c.163.com/library/ubuntu tar xvf /backup/vof.tar
datavolume1/
datavolume1/vo_file
datavolume1/vo_file1
datavolume1/vo_file2

然后创建一个容器挂载votest8

[root@localhost backup]# docker run -it --volumes-from votest8 hub.c.163.com/library/ubuntu /bin/bash
root@ee4d4f932ce4:/# 
root@ee4d4f932ce4:/# ls
backup  bin  boot  datavolume1  dev  dockervolume2  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@ee4d4f932ce4:/# cd backup/ 
root@ee4d4f932ce4:/backup# ll
-rw-r--r--.  1 root root 10240 Mar 24 06:44 vof.tar
root@ee4d4f932ce4:/backup# 

以上就是数据卷和数据卷容器的相关操作。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐