文章目录
用户在使用 Docker 的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据的共享,这必然涉及容器的数据管理操作。容器中管理数据主要有两种方式:数据卷(Data Volumes),数据卷容器(Data Volume Containers)。
一、数据卷
1. 什么是数据卷:
- 数据集是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或多个容器提供访问
- 数据卷设计的目的,在于数据的持久化,它完全独立于容器的生存周期,因此,Docker不会在容器删除时删除其挂载的数据卷,也不会存在类似的垃圾回收机制,对容器引用的数据卷进行处理。
根据上图docker数据卷的结构可知:
- docker数据卷是独立于docker的存在,它存在于宿主机中,因此,它与docker容器的生存周期是分离的
- docker数据卷可以是目录,也可以是文件
- docker容器可利用数据集技术与宿主机实现数据共享
- 同一个目录或文件可以支持多个容器的访问,这样实际上实现了容器间数据的共享和交换
2. 数据卷的特点:
- 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据集中
- 数据卷可以在容器之间共享和重用
- 可以对数据卷的内容直接进行修改
- 数据卷的变化不会影响镜像的更新
- 卷会一直存在,即使挂载数据卷的容器已经被删除
3. 使用数据卷的最佳场景:
- 在多个容器之间共享数据,多个容器可以同时以只读或者读写的方式挂载同一个数据卷,从而共享数据卷中的数据。
- 当宿主机不能保证一定存在某个目录或一些固定路径的文件时,使用数据卷可以规避这种限制带来的问题。
- 当你想把容器中的数据存储在宿主机之外的地方时,比如远程主机上或云存储上。
- 当你需要把容器数据在不同的宿主机之间备份、恢复或迁移时,数据卷是很好的选择。
4. 数据卷的使用:
4.1 容器创建时添加数据卷
例如:启动一个Ubuntu容器,并添加一个数据卷
本机文件系统中的目录:在容器中映射的目录
docker run -v /datavolume:/data -it ubuntu bash
这样的话,在容器该目录中进行的操作实际上就是对宿主机上相应目录的操作
比如,在容器中的data目录上新建一个文件test,填入相应内容,则在宿主机datavolume目录下也会有相应的变化
4.2 docker volume 子命令
docker 专门提供了 volume 子命令来操作数据卷:
docker volume create <name> 创建数据卷
docker volume inspect <name> 显示数据卷的详细信息
docker volume ls 列出所有的数据卷
docker volume prune 删除所有未使用的 volumes,并且有 -f 选项
docker volume rm <name>... 删除一个或多个未使用的 volumes,并且有 -f 选项
4.3 使用 mount 语法挂载数据卷
之前我们使用 --volume(-v) 选项来挂载数据卷,现在 docker 提供了更强大的 --mount 选项来管理数据卷。mount 选项可以通过逗号分隔的多个键值对一次提供多个配置项,因此 mount 选项可以提供比 volume 选项更详细的配置。使用 mount 选项的常用配置如下:
- type 指定挂载方式,我们这里用到的是 volume,其实还可以有 bind 和 tmpfs。
- volume-driver 指定挂载数据卷的驱动程序,默认值是 local。
- source 指定挂载的源,对于一个命名的数据卷,这里应该指定这个数据卷的名称。在使用时可以写 source,也可以简写为 src。
- destination 指定挂载的数据在容器中的路径。在使用时可以写 destination,也可以简写为 dst 或 target。
#例如:
#创建名为 hello 的数据卷,然后把它挂在到容器中的 /world 目录。
docker volume create hello
docker run -it --mount type=volume,source=hello,target=/world ubuntu /bin/bash
二、数据卷容器
1. 什么是数据卷容器:
命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器,就叫做数据卷容器
2. 使用数据卷容器:
#创建数据卷容器
#这里实际上就是启动了一个普通的容器,并在其中创建一个数据卷挂载到 /data 目录
docker run -it -v /data –name mydata ubuntu
#然后在其他容器中就可以使用 --volumes-from 来挂载 mydata 容器中的数据卷
docker run -it --volumes-from mydata –name mycon1 ubuntu
docker run -it --volumes-from mydata –name mycon2 ubuntu
#此时容器 mycon1 和 mycon2 都挂载同一个数据卷到相同的目录 /data。三个容器任何一个在该目录下写入数据其他容器都能看到。
删除挂载了数据卷的容器时,数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式的使用 docker rm -v 命令来指定同时删除关联的容器。
三、一个简单的实践
docker部署数据库:数据库的存储必须要持久化,不能出现容器一删除,数据库也被删除。这个时候就用到了数据卷
- 拉取mysql镜像
mysql已经出到8版本了,有了比较重大的升级,我们这里使用的是5.7.25的版本
docker pull mysql:5.7.25
- 创建将要映射到容器中的目录以及.cnf文件
mkdir -p /home/nic/docker/mysql/conf
mkdir -p /home/nic/docker/mysql/data/mysql
cd /home/nic/docker/mysql/conf
touch my.cnf
- 运行容器
docker run -p 3306:3306 --name mysql \
-v /home/nic/docker/mysql/conf:/etc/mysql/conf.d \
-v /home/nic/docker/mysql/data/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456\
-d mysql:5.7.25
命令参数:
- -p 3306:3306:将宿主机的3306端口映射到容器的3306端口
- -v /home/nc/docker/mysql/conf/my.cnf:/etc/mysql/my.cnf:将主机当前目录下的conf/my.cnf挂载到容器的 /etc/mysql/my.cnf
- -v /home/nc/docker/mysql/data/mysql:/var/lib/mysql:将主机当前目录下的 data 目录挂载到容器的 /var/lib/mysql
- -e MYSQL_ROOT_PASSWORD=123456:初始化root用户的密码
- 使用Navicat连接并导入数据库
解决登录权限问题:
- 编辑mysql配置文件,暂时跳过登录验证
vi /home/nic/docker/mysql/conf/my.cnf
[mysqld]
skip-grant-tables
-
重新启动mysql容器,并进入容器,登录mysql
-
重新设置密码
#使用mysql自带的mysql数据库。
use mysql;
#更改user表下的密码。
UPDATE user SET authentication_string = password ( 'a123456' ) WHERE User = 'root';
#刷新权限
flush privileges;
#退出
quit;
- 删除第一步的跳过认证启动
- 重新启动mysql容器
解决外部拒绝访问问题:
进入容器,登录mysql
#添加远程登录用户
CREATE USER 'liaozesong'@'%' IDENTIFIED WITH mysql_native_password BY 'Lzslov123!';
GRANT ALL PRIVILEGES ON *.* TO 'liaozesong'@'%';