Docker数据管理
容器中的管理数据主要有两种方式:
- 数据卷(Data Volumes):容器内数据直接映射到本地主机环境
- 数据卷容器(Data Volume Containers):使用特定容器维护数据卷
数据卷
数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似于Linux中的mount行为。
数据卷可提供很多有用的特性:
- 数据卷可以在容器之间共享和重用,容器间传递数据将变得高效和方便;
- 对数据卷内的数据修改会立马生效,无论是容器内操作还是本地操作
- 对数据卷的更新不会影响镜像,解耦开应用和数据
- 卷会一直存在,直到没有容器使用,可以安全地卸载它
使用数据卷
docker run -it -v 主机目录:容器内目录
测试:
#主机目录下面没有ceshi目录
[root@aliyun home]# ll
总用量 12
drwxr-xr-x 2 root root 4096 4月 15 15:07 docker
drwxr-xr-x 3 root root 4096 4月 6 17:03 python
drwxr-xr-x 2 root root 4096 3月 25 15:46 shell
#将主机上的/home/ceshi目录挂载到容器内部的/home
[root@aliyun home]# docker run -it -v /home/ceshi:/home centos /bin/bash
#进入容器
[root@e4042f5dff6d /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
#切换到容器内的/home目录
[root@e4042f5dff6d /]# cd /home/
#查看容器内/home目录下内容,空目录
[root@e4042f5dff6d home]# ls
#新建一个hello.txt文件
[root@e4042f5dff6d home]# vi hello.txt
#查看hello.txt文件内容
[root@e4042f5dff6d home]# cat hello.txt
Hello World
#查看主机上/home/ceshi路径下的内容
[root@aliyun ~]# ls
interview tools
[root@aliyun ~]# cd /home/ceshi/
[root@aliyun ceshi]# ll
总用量 4
-rw-r--r-- 1 root root 12 4月 19 09:11 hello.txt
[root@aliyun ceshi]# cat hello.txt
Hello World
###发现容器内/home目录下的内容会自动同步到宿主机中/home/ceshi目录下
#同理,测试宿主机中/home/ceshi目录下新建的文件或修改文件内容是否会自动同步到容器内/home目录
#修改hello.txt文件内容
[root@aliyun ceshi]# vim hello.txt
#查看hello.txt文件内容,新增一行Hello Torres!!!
[root@aliyun ceshi]# cat hello.txt
Hello World
Hello Torres!!!
#新建一个test.txt文件
[root@aliyun ceshi]# touch test.txt
[root@aliyun ceshi]# ll
总用量 4
-rw-r--r-- 1 root root 28 4月 19 09:18 hello.txt
-rw-r--r-- 1 root root 0 4月 19 09:18 test.txt
#查看容器内/home目录下内容
[root@e4042f5dff6d home]# ls -al
total 12
drwxr-xr-x 2 root root 4096 Apr 19 01:18 .
drwxr-xr-x 1 root root 4096 Apr 19 01:10 ..
-rw-r--r-- 1 root root 28 Apr 19 01:18 hello.txt
-rw-r--r-- 1 root root 0 Apr 19 01:18 test.txt
[root@e4042f5dff6d home]# cat hello.txt
Hello World
Hello Torres!!!
实战:安装MySql
#拉取镜像
[root@aliyun ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
72a69066d2fe: Pull complete
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
#运行容器,需要做数据挂载(注意:启动mysql,需要设置密码)
#官方启动命令
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#自己启动
-d:后台启动
-p:端口映射
-v:数据卷挂载
-e:设置环境变量
--name:定义容器名
[root@aliyun ~]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name=mysql01 mysql:5.7
6e755c41e69700decc8d6bb5966dbb82f6cb1dd6666975185445d8674d2b0704
#docker ps查看启动状态
[root@aliyun ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6e755c41e697 mysql:5.7 "docker-entrypoint.s…" 38 seconds ago Up 37 seconds 33060/tcp, 0.0.0.0:3310->3306/tcp mysql01
#查看宿主机/home目录
[root@aliyun home]# ll
总用量 20
drwxr-xr-x 2 root root 4096 4月 19 09:18 ceshi
drwxr-xr-x 2 root root 4096 4月 15 15:07 docker
drwxr-xr-x 4 root root 4096 4月 19 10:31 mysql
drwxr-xr-x 3 root root 4096 4月 6 17:03 python
drwxr-xr-x 2 root root 4096 3月 25 15:46 shell
#查看mysql目录,发现挂载成功
[root@aliyun home]# cd mysql/
[root@aliyun mysql]# ll
总用量 8
drwxr-xr-x 2 root root 4096 4月 19 10:31 conf
drwxr-xr-x 5 polkitd root 4096 4月 19 10:31 data
这样子就可以不用进入容器去修改数据等,同时也将数据存储到了本地。
思考:如果容器删除,本地数据是否也会跟着删除?
#删除mydql01容器
[root@aliyun ~]# docker rm -f mysql01
mysql01
[root@aliyun ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
#mysql01删除成功
[root@aliyun ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e4042f5dff6d centos "/bin/bash" 2 hours ago Exited (0) 53 minutes ago inspiring_volhard
7b913eab7ec9 fb5657adc892 "/bin/bash" 2 hours ago Exited (0) 2 hours ago tomcat01
#查看宿主机/home/mysql目录
[root@aliyun mysql]# pwd
/home/mysql
[root@aliyun mysql]# ll
总用量 8
drwxr-xr-x 2 root root 4096 4月 19 10:31 conf
drwxr-xr-x 5 polkitd root 4096 4月 19 10:31 data
结论:当容器删除,宿主机对应挂载目录下内容依旧存在。
具名挂载和匿名挂载
#匿名挂载(即不指定本地挂载目录,使用docker的默认挂载目录)
[root@aliyun ~]# docker run -d -P -v /etc/nginx --name=nginx01 nginx
9afbc16cec6c7f48f856faa1d4d8e15abb661ac8563e133832b80ee6efcb70b9
#查看所有volume的情况
[root@aliyun ~]# docker volume ls
DRIVER VOLUME NAME
local 0c6e50ec3765f8b35ec4538836b8a987eb7ee893eecf4e1d9c61de61c0e2b2f5
#查看容器的具体信息
[root@aliyun ~]# docker inspect nginx01
···
"Mounts": [
{
"Type": "volume",
"Name": "0d46c494e6c57f919827871a6810171c46f2999c00e63b2197e6623206556ff6",
"Source": "/var/lib/docker/volumes/0d46c494e6c57f919827871a6810171c46f2999c00e63b2197e6623206556ff6/_data",
"Destination": "/etc/nginx",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
···
#具名挂载(指定宿主机挂载路径)
[root@aliyun ~]# docker run -d -P -v juming_nginx:/etc/nginx --name=nginx02 nginx
c43e0f78971a88cebacf138e9b1b8516222c001cf72af3e4df8c83749c5f560e
#查看卷信息
[root@aliyun ~]# docker volume ls
DRIVER VOLUME NAME
local 0c6e50ec3765f8b35ec4538836b8a987eb7ee893eecf4e1d9c61de61c0e2b2f5
local 0d46c494e6c57f919827871a6810171c46f2999c00e63b2197e6623206556ff6
local 00442e8628703dd84374e7512833e1889a0a6cea32172be79ff792e29b138fd7
local b2af5d99231a0aa2c446b10ac1e8ba774a04253e8e27de155779fe061ea2467a
local juming_nginx
#查看容器信息
[root@aliyun ~]# docker inspect nginx02
···
"Mounts": [
{
"Type": "bind",
"Source": "juming_nginx",
"Destination": "/etc/nginx",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
···
所有docker容器内的卷,在没有指定路径的情况下,默认挂载目录为:/var/lib/docker/volumes/XXX/_data
如何区分挂载方式?
- -v 容器内路径(匿名)
- -v 卷名:容器内路径(具名)
- -v 宿主机路径(绝对路径):容器内路径(指定路径挂载)
扩展
- 通过-v容器内路径:ro/rw改变读写权限
ro:readonly(容器只读)
rw:readwrite(容器读写)
- 一旦设置了这个容器权限,容器对我们挂载出来的内容就有限定了
docker run -d -P --name nginx01 v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx01 v juming-nginx:/etc/nginx:rw nginx
只要看到ro,说明这个路径只能通过宿主机来改变,容器对所挂载数据卷内的数据就无法修改了。
数据卷容器
如果用户需要在多个容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器也是一个容器,其目的是专门提供数据卷给其他容器使用
#创建一个数据卷容器dbdata,并在其中创建一个数据卷挂载到/dbdata
[root@aliyun ~]# docker run -it -v /dbdata --name dbdata centos
#查看/dbdata目录
[root@b806186465ba /]# ls
bin dbdata dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@b806186465ba /]# cd dbdata
[root@b806186465ba dbdata]# ls
#其他容器使用--volume-from来挂载dbdata容器中的数据卷,创建db1和db2容器
[root@aliyun ~]# docker run -it --volumes-from dbdata --name db1 centos
#db1
[root@70f46c3b15dc /]# ls
bin dbdata dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
[root@aliyun ~]# docker run -it --volumes-from dbdata --name db2 centos
#db2
[root@d94f48a32c2d /]# ls
bin dbdata dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
容器db1和db2都挂载到同一个数据卷到相同的/dbdata目录,三个容器任何一方在该目录下的写入,其他容器都可以看到。
#在dbdata容器中创建一个test文件
[root@b806186465ba dbdata]# pwd
/dbdata
[root@b806186465ba dbdata]# touch test.sh
#在db1容器中查看
[root@70f46c3b15dc /]# cd dbdata/
[root@70f46c3b15dc dbdata]# ls
test.sh
#在db2容器中查看
[root@d94f48a32c2d /]# cd /dbdata/
[root@d94f48a32c2d dbdata]# ls
test.sh
可以多次使用--volumes-from参数来从多个容器挂载多个数据卷,还可以从其他已挂载了容器卷的容器来挂载数据卷
[root@aliyun ~]# docker run -d --name db3 --volumes-from db1 centos
注意:使用--volumes-from参数所挂载数据卷的容器自身并不需要保持在运行状态
如果删除了挂载的容器(dbdata、db1和db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个 还挂载它的容器时显示使用 docker rm -v
命令来指定同时删除关联的容器。
利用数据卷容器来迁移数据
可利用数据卷容器对其中的数据卷进行备份、恢复,以实现数据的迁移。
备份
$ docker run --volumes-from dbdata -v $(pwd):/backup --name worker centos tar -cvzf /backup/backup.tar.gz /dbdata
解析:
首先利用centos镜像创建了一个容器worker,使用--volumes-from dbdata
参数让worker容器挂载dbdata容器的数据卷(即dbdata数据卷);使用-v $(pwd):/backup
参数来挂载本地的当前目录到worker容器的/backup目录
worker容器启动后,使用tar -cvzf /backup/backup.tar.gz /dbdata
将/dbdata下内容打包备份为容器内的/backup/backup.tar.gz
,即宿主机当前目录下的backup.tar.gz
恢复
如果要恢复数据到一个容器,操作如下:
#创建一个带有数据卷的容器dbdata2
$ docker run -v /dbdata --name dbdata2 centos /bin/bash
#再创建一个新的容器,挂载dbdata2的容器,并使用tar解压备份文件到所挂载的容器中
$ docker run --volumes-from dbdata2 -v $(pwd):/backup centos tar -xvzf /backup/backup.tar.gz