容器中管理数据主要有两种方式
数据卷:容器内的数据直接映射到本地主机目录。
数据卷容器:使用特定的容器维护数据卷。
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
没有创建容器之前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