docker 数据管理

容器中管理数据主要有两种方式

数据卷:容器内的数据直接映射到本地主机目录。

数据卷容器:使用特定的容器维护数据卷。

Docker提供三种不同的方式将数据从宿主机挂载到容器中:volumes,bind mounts和tmpfs。

1)volumes:Docker管理宿主机文件系统的一部分(/var/lib/docker/volumes)。
2)bind mounts:可以存储在宿主机系统的任意位置。
3)tmpfs:挂载存储在宿主机系统的内存中,而不会写入宿主机的文件系统。

数据卷

 

1、volumes

数据卷是一个可供容器使用的特殊目录,有如下特性:
1)数据卷可以在容器之间共享和重用
2)数据卷修改会立即生效
3)数据卷的更新不会影响镜像
4)如果有容器使用数据卷,该卷会一直存在

1.在容器内创建一个数据卷

[root@docker01 ~]#  docker volume create nginx-vol
nginx-vol
[root@docker01 ~]# docker volume ls
DRIVER              VOLUME NAME
local               01da511ea2d414af458ab07e8c2364408206599d05f4f395d9c1da7e148d42af
local               0bddbe54988d963500402a02ec50530d8ea0b3999ac2aa40814cd54a5360cb8f
local               nginx-vol
[root@docker01 ~]# ll /var/lib/docker/volumes/
drwxr-xr-x  3 root root    19 Feb 22 08:49 01da511ea2d414af458ab07e8c2364408206599d05f4f395d9c1da7e148d42af
drwxr-xr-x  3 root root    19 Feb 22 09:10 0bddbe54988d963500402a02ec50530d8ea0b3999ac2aa40814cd54a5360cb8f
drwxr-xr-x  3 root root    19 Mar 12 08:47 nginx-vol
[root@docker01 ~]#  docker volume inspect nginx-vol
[
    {
        "CreatedAt": "2019-03-12T08:47:17+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/nginx-vol/_data",
        "Name": "nginx-vol",
        "Options": {},
        "Scope": "local"
    }
]

2.用卷创建一个容器:

具名卷:

# docker run -d --name=nginx-test --mount src=nginx-vol,dst=/usr/share/nginx/html nginx
# docker run -d --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx

匿名卷:

docker run -d --name=nginx-test -v /usr/share/nginx/html nginx

补充:对于Dockerfile中的VOLUME声明的卷均为匿名卷,对卷内数据修改只能在VOLUME声明前,在其后对卷内数据修改均不生效。

没有创建容器之前volume里面没有内容,创建完成后:

[root@docker01 ~]# docker run -d --name=nginx-test -v nginx-vol:/usr/share/nginx/html nginx
ce12107a9ef40f26499d083c4f6b6200b3263d30f272144ff0f031670a9fe142
[root@docker01 ~]# ls /var/lib/docker/volumes/nginx-vol/_data/
50x.html  index.html

我们可以看到容器内的对应目录内容会自动映射到主机目录,由此可见数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于Linux中的mount操作。

停止并删除容器,修改index.html的内容,再创建一个可以对外访问的容器。

[root@docker01 ~]# docker rm -f nginx-test
nginx-test
[root@docker01 ~]# ls /var/lib/docker/volumes/nginx-vol/_data/
50x.html  index.html
[root@docker01 ~]# echo "hello docker" >/var/lib/docker/volumes/nginx-vol/_data/index.html 
[root@docker01 ~]# cat /var/lib/docker/volumes/nginx-vol/_data/index.html
hello docker

[root@docker01 ~]# docker run -d --name=nginx-test -p 88:80 -v nginx-vol:/usr/share/nginx/html nginx
8a4bb5c618993fbdcc171bdbcd782476e15532ec38cb956d2a3719f821a47373
[root@docker01 ~]# curl 10.0.0.99:88
hello docker

很明显,此种方式,数据卷的内容覆盖容器中对应的默认数据,数据卷可以在容器之间共享和重用。
注意:如果没有指定卷,会自动创建

[root@docker01 ~]# docker run -d --name=nginx-test2 -v nginx-test:/usr/share/nginx/html nginx
af521547cbc090268dd3151ceefa07660b918760ac2bd9170b6c9bbae7cb1d0b
[root@docker01 ~]# docker volume ls
DRIVER              VOLUME NAME
local               01da511ea2d414af458ab07e8c2364408206599d05f4f395d9c1da7e148d42af
local               0bddbe54988d963500402a02ec50530d8ea0b3999ac2aa40814cd54a5360cb8f
local               nginx-test
local               nginx-vol

清理:

[root@docker01 ~]# docker rm -f `docker ps -aq`

2、bind mounts:

此种方式均以"/"开头,挂载的为宿主机的指定目录。(不推荐,有空挂载问题!)

用卷创建一个容器:
第一种方式:指定的src目录必须存在,否则将报错

# docker run -d -it --name=nginx-test --mount type=bind,src=/app/wwwroot,dst=/usr/share/nginx/html nginx

[root@docker01 ~]#  docker run -d -it --name=nginx-test --mount type=bind,src=/test/app,dst=/usr/share/nginx/html nginx
docker: Error response from daemon: invalid mount config for type "bind": bind mount source path does not exist: /test/app.

第二种方式:如果没有指定卷,会自动创建

# docker run -d -it --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html nginx
[root@docker01 ~]# docker run -d -it --name=nginx-test -v /app/wwwroot:/usr/share/nginx/html nginx
6000fe0e1e8a49f2ad6a34cb2bef78c064ad4090c06de4ebc12619da1727f7d9
[root@docker01 ~]# ls /app/wwwroot/
[root@docker01 ~]# docker exec -it nginx-test bash
root@6000fe0e1e8a:/# ls /usr/share/nginx/html/
root@6000fe0e1e8a:/#

由此可见,bind mounts方式,挂载一个主机目录作为数据卷,无论主机目录是否为空则都会覆盖容器内对应的目录。

清理:

# docker stop nginx-test
# docker rm nginx-test

数据卷容器

数据卷容器用于用户需要在容器间共享一些持续更新的数据,数据卷容器专门提供数据卷供其它容器挂载使用。
1.数据卷容器创建
创建数据卷容器dbdata,并查看/dbdata目录。

[root@docker01 ~]# docker run -itd --name dbdata -v /dbdata centos
0a886be8adcad08eabf407bf8c862044a35bf592373068aed1dbc313ff9b785b
[root@docker01 ~]# docker exec -it dbdata bash
[root@0a886be8adca /]# ls
anaconda-post.log  bin  dbdata  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

创建容器db1与db2共享dbdata的数据,需要使用--volumes-from来挂载dbdata容器中的数据卷。

[root@docker01 ~]# docker run -itd --name db1 --volumes-from dbdata centos
12d0bb5e53051ecc17c660533e9f66ee0f57d93891851699c08321433ebdfc65
[root@docker01 ~]# docker run -itd --name db2 --volumes-from dbdata centos
3e9292a1edc77016e5574c8efdb906f9f67f2b3426cedbd0dfd4667a06798bf5

此时,容器db1和容器db2都挂载同一个数据卷到相同的/dbdata目录。三个容器任意一个容器修改dbdata的内容,其他容器内均生效
在dbdata内创建一个test文件,其他都能看见:

[root@docker01 ~]# docker exec -it dbdata bash
[root@0a886be8adca /]# cd /dbdata/
[root@0a886be8adca dbdata]# ls
[root@0a886be8adca dbdata]# touch test
[root@0a886be8adca dbdata]# ls
test
[root@0a886be8adca dbdata]# exit
exit
[root@docker01 ~]# docker exec -it db1 bash
[root@12d0bb5e5305 /]# ls dbdata/
test
[root@12d0bb5e5305 /]# exit
exit
[root@docker01 ~]# docker exec -it db2 bash
[root@3e9292a1edc7 /]# ls dbdata/
test
[root@3e9292a1edc7 /]#

2.数据卷容器的删除

如果删除了挂载的容器,数据卷并不会被自动删除,如果要删除一个数据卷,必须在删除最后一个还挂载它的容器时显示使用docker rm -v 命令指定同时删除关联的容器。 

3.数据迁移:
可以利用数据卷容器对其中的数据卷进行备份、恢复,以实现数据的迁移。

1)备份:
使用下面的命令来备份dbdata数据卷容器内的数据卷:

docker run --volumes-from dbdata -v /root:/backup --name worker centos tar cvf /backup/backup.tar /dbdata

[root@docker01 ~]# docker run --volumes-from dbdata -v /root:/backup --name worker centos tar cvf /backup/backup.tar /dbdata
tar: Removing leading `/' from member names
/dbdata/
/dbdata/test
[root@docker01 ~]# ls                   
backup.tar

说明:    
利用centos镜像创建一个容器worker。使用--volumes-from dbdata参数来让worker容器挂载dbdata的数据卷;使用/root:/backup参数来挂载本地目录到worker容器的/backup目录。   
worker启动后,使用tar命令将/dbdata下的内容备份为容器内的/backup/backup.tar,即宿主机root目录下的backup.tar。

2)恢复:
如果恢复数据到一个容器,可以参照下面的操作。
首先创建一个带有数据卷的容器dbdata2,然后创建另一个新的容器,挂载dbdata2的容器,并使用tar命令解压备份文件到挂载的容器卷中即可:

[root@docker01 ~]# docker run -itd -v /dbdata --name dbdata2 centos
9f79dad9170e2b99d1e661ce57279495dc2e3afe1e65d42890406a2a65b65c6e
[root@docker01 ~]# docker run --volumes-from dbdata2 -v /root:/backup centos tar xvf /backup/backup.tar
dbdata/
dbdata/test
[root@docker01 ~]# docker exec -it dbdata2 bash
[root@9f79dad9170e /]# ls dbdata/
test

 注意:

  • 所以对卷数据修改,使用docker commit提交所以变化为镜像时,会丢弃卷内数据,即不会将挂载修改的数据保存新镜像中。
  • VOLUME声明的目录,容器启动将进行自动挂载,挂载宿主机内部的为匿名卷。
  • 挂载只有一点,就是方便在容器外部修改数据,或者直接将外数据直接拿来使用。
posted @ 2019-03-12 13:35  ThreeCode  阅读(482)  评论(1编辑  收藏  举报