为什么要做数据持久化?
当容器运行期间产生的数据是不会在写镜像里面的,重新用此镜像启动新的容器就会初始化镜像,会加一个全新的读写层来保存数据。如果想做到数据持久化,Docker提供数据卷(Data volume)或者数据容器卷来解决问题,另外还可以通过commit提交一个新的镜像来保存产生的数据。
Docker数据持久化方案:
- 基于本机文件系统的Volume。可以执行
Docker create
或Docker run
时,通过-v
参数将主机的目录作为容器的数据卷。这部分功能便是基于本地文件系统的volume管理。 - 基于plugin的Volume,支持第三方的存储方案,比如NAS,AWS。
基于本机文件系统的Volume:
- Data Volume:挂载数据卷
- Bind Mouting: 挂载本地目录
数据持久化之Data Volume:
1.下载mysql镜像
[root@localhost ~]# docker search mysql //搜索mysql镜像 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 9468 [OK] [root@localhost ~]# docker pull mysql //下载mysql镜像 ... bcc6c6145912: Pull complete 951c3d959c9d: Extracting [===============================================> ] 3.998MB/4.178MB [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE mysql latest a7a67c95e831 10 days ago 541MB
2.启动mysql1容器并查看容器内与容器外的volume对象
-i:以交互模式运行容器,通常与 -t 同时使用
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用
-d:后台运行
--name 容器名: 为容器指定一个名称
-e:操作mysql的内部命令
--MYSQL_ALLOW_EMPTY_PASSWORD=true:代表密码设置为空
[root@localhost ~]# docker run -itd --name mysql1 -e MYSQL_ROOT_PASSWORD=123 mysql:latest 109d0290ccbfe0d6d335b0e9842c770f21123b3ba42587bb8b389765c2be063c //指定容器名称为mysql1,-e设置mysql1容器数据库密码为123 [root@localhost ~]# docker volume ls DRIVER VOLUME NAME local 8931d175e3b22ea7d963d76b1ea2ee9347b546ddfb86ab17940fac44466acd03 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 109d0290ccbf mysql:latest "docker-entrypoint.s…" 19 minutes ago Up 19 minutes 3306/tcp, 33060/tcp mysql1
可以看到如果不指定-v参数就直接启动mysql1容器,那么默认产生的volume对象就是一串ID。
3.删除mysql1容器,查看volume对象是否被删除
[root@localhost ~]# docker stop mysql1 mysql1 [root@localhost ~]# docker rm mysql1 mysql1 [root@localhost ~]# docker volume ls DRIVER VOLUME NAME local 8931d175e3b22ea7d963d76b1ea2ee9347b546ddfb86ab17940fac44466acd03
可以看到在删除mysql1容器后,这个volume对象并没有随着容器的删除而丢失。
4.删除之前mysql1容器默认生成的volume对象
[root@localhost ~]# docker volume ls DRIVER VOLUME NAME local 8931d175e3b22ea7d963d76b1ea2ee9347b546ddfb86ab17940fac44466acd03 [root@localhost ~]# docker volume rm 8931d175e3b22ea7d963d76b1ea2ee9347b546ddfb86ab17940fac44466acd03 8931d175e3b22ea7d963d76b1ea2ee9347b546ddfb86ab17940fac44466acd03
5.启动mysql2容器并指定volume对象名称(挂载目录)
-v:挂载宿主机的一个目录/数据卷(宿主机目录如果不存在,则会自动创建)
用法:-v 宿主机目录/数据卷:容器内目录(容器目录必须为绝对路径)
docker volume管理命令:
docker volume create 数据卷:--> 创建volume
docker inspect 数据卷:--> 查看数据卷信息
docker run -itd -v 数据卷:容器内目录:--> 使用某个数据卷
docker volume ls:--> 列出所有数据卷
docker volume rm 数据卷:--> 删除某个数据卷
[root@localhost ~]# docker run -itd --name mysql2 -v mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 mysql 1d90619790ecb9ff9bd63524048fef777a39b8cb14652eade5b1551e30bd4964 //数据卷mysql若不存在,则会自己创建 [root@localhost ~]# docker volume ls DRIVER VOLUME NAME local mysql [root@localhost ~]# docker volume inspect mysql [ { "CreatedAt": "2020-05-09T03:01:17+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/mysql/_data", "Name": "mysql", "Options": null, "Scope": "local" } ]
因为我们挂载时没有指定mysql目录绝对路径,用volume inspect
可以查看volume挂载的信息,若挂载宿主机目录时不使用绝对路径,则默认挂载在/var/lib/docker/volumes/目录下,也可以指定路径(如:-v /mnt/mysql:/var/lib/mysql)
验证Data Volume持久化:
1.进入mysql2容器创建test库并删除容器mysql2
[root@localhost ~]# docker exec -it mysql2 /bin/bash root@1d90619790ec:/# mysql -uroot -p123 ... mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.68 sec) mysql> create database test; //创建test库 Query OK, 1 row affected (0.24 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | test | +--------------------+ 5 rows in set (0.01 sec) [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1d90619790ec mysql "docker-entrypoint.s…" 3 hours ago Up 3 hours 3306/tcp, 33060/tcp mysql2 [root@localhost ~]# docker rm -f mysql2 //强制删除mysql2容器 mysql2
2.新启动mysql3容器,并使用-v参数挂载之前的mysql数据卷
[root@localhost ~]# docker run -itd --name mysql3 -v mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123 mysql 96a5f81cd671f57cb52df89ae5ae130207aec454f4f55d4746b00a8655ed5113 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 96a5f81cd671 mysql "docker-entrypoint.s…" 27 seconds ago Up 16 seconds 3306/tcp, 33060/tcp mysql3 [root@localhost ~]# docker exec -it mysql3 /bin/bash
3.进入mysql3容器,查看mysql数据卷中的数据是否还在
[root@localhost ~]# docker exec -it mysql3 /bin/bash root@96a5f81cd671:/# mysql -uroot -p123 ... mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | test | ---》test库依然存在 +--------------------+ 5 rows in set (0.01 sec)
Data Volume 数据共享:
数据卷可以被挂载到多个容器中,这时候数据卷中的数据被共享。
如果要共享数据卷,需要使用--volumes-from
参数。
1.进入mysql3容器,查看mysql数据卷数据
[root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 96a5f81cd671 mysql "docker-entrypoint.s…" 2 days ago Up 7 seconds 3306/tcp, 33060/tcp mysql3 [root@localhost ~]# docker exec -it mysql3 /bin/bash root@96a5f81cd671:/# mysql -uroot -p123 ... mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | test | -----》之前创建的test库 +--------------------+ 5 rows in set (0.01 sec)
2.新启动mysql4容器,共享mysql数据卷
注意:
在启动mysql4容器之前,需要先停止mysql3数据库容器,经测试不能同时开启做数据共享(使用同一个数据卷)的两个mysql容器。
[root@localhost ~]# docker stop mysql3 //停止mysql3容器 mysql3 [root@localhost ~]# docker run -itd --name mysql4 --volumes-from mysql3 -e MYSQL_ROOT_PASSWORD=123 mysql 7632976b82d40de79ed0c165d0f7d0757fd4e1088fb638ed405c0a67c9656cf1 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7632976b82d4 mysql "docker-entrypoint.s…" 38 seconds ago Up 37 seconds 3306/tcp, 33060/tcp mysql4
3.进入mysql4容器,查看数据库中共享数据卷mysql后的数据
[root@localhost ~]# docker exec -it mysql4 /bin/bash root@7632976b82d4:/# mysql -uroot -p123 ... mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | test | ---》可以看到mysql数据卷中的数据的确存在 +--------------------+ 5 rows in set (0.01 sec)