在Docker中,image是只读的,而container是在image之上的一个新的层,container是可读可写的,我们可以在container中写入数据.但是在container中写入的数据仅存在于当前的container,一旦该container被删除,则其中的数据也将不复存在.若如我们的container是一个数据库的服务,则其中的数据决不可仅存在与该container中,为此docker引入了数据持久化存储的机制.
Docker持久化数据的方案
- 基于本地文件系统的Volume: 可以在执行 docker create 或 docker run 时,通过 -v 参数将主机的目录作为容器的数据卷.这是基于本地文件系统的volume管理.
- 基于plugin的Volume: 可以支持第三方的存储方案,比如将数据存储在NAS, aws.
基于本地文件系统中的volume中,volume分两类
- 受管理的 data volume: 它由docker后台自动创建,不管加不加 -v 参数,docker后台都会帮我们创建一个data volume,位置是固定的,名字是随机的.
- 绑定挂载的volume: 具体挂载位置可以由用户指定 , 需要通过参数去指定container中的某个目录产生的数据具体要挂载到本地硬盘的某个目录下.
1.Data Volume
通过Dockerfile中的关键字"Volume"可以指定容器中需要数据持久化数据的目录.
打开 DockerHub 官方的 mysql 的 Dockerfile,其中有一行的内容为
VOLUME /var/lib/mysql
通过命令"docker run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql" 创建一个 mysql 数据库服务的 container,通过 -e 参数设置环境变量,是其登录数据库时不需要密码.
通过命令 "docker volume list" 可以看到在本地生成了一个volume,及时将数据库container删除,该volume也不会消失
通过命令 "docker volume rm volumeID" 可以删除volume
通过命令 "docker volume inspect volumeID" 可以查看volume的具体信息,如本地的挂载点 "Mountpoint" 等
[vagrant@localhost ~]$ docker run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
1a5426eb27ffdc937e7b5bb4e49bb180994b9eac51457863c95dfdaeb133b281
[vagrant@localhost ~]$ docker volume list
DRIVER VOLUME NAME
local 2f899bc3ff627c425e0513728169379b598a8eb6e7b75a91eb7708c75978650e
[vagrant@localhost ~]$ docker volume inspect 2f899bc3ff627c425e0513728169379b598a8eb6e7b75a91eb7708c75978650e
[
{
"CreatedAt": "2019-01-11T04:50:53Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/2f899bc3ff627c425e0513728169379b598a8eb6e7b75a91eb7708c75978650e/_data",
"Name": "2f899bc3ff627c425e0513728169379b598a8eb6e7b75a91eb7708c75978650e",
"Options": null,
"Scope": "local"
}
]
默认的volume名字不够友好,我们可以通过 " -v 指定的名字: 容器中数据目录" 为其指定名字
[vagrant@localhost ~]$ docker run -d -v mysql1_volume:/var/lib/mysql --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
51f57634d4a6c6893c22fa656cf15cc14bb589b46edcdba2e8cc5877487225b5
[vagrant@localhost ~]$ docker volume ls
DRIVER VOLUME NAME
local mysql1_volume
data volume的数据共享,即两个不同的container是可以共享同一个volume中的数据的
基于以上内容,我们为mysql1在本地挂载了一个名为 "myaql1_volume" 的volume, 下面我们对myaql1_volume做一些修改,然后将mysql1删除
[vagrant@localhost ~]$ docker exec -it mysql1 /bin/sh
# mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.13 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
4 rows in set (0.07 sec)
mysql> create database docker;
Query OK, 1 row affected (0.06 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| docker |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> exit
Bye
# exit
[vagrant@localhost ~]$ docker rm -f mysql1
mysql1
[vagrant@localhost ~]$ docker volume ls
DRIVER VOLUME NAME
local mysql1_volume
接下来,我们创建另一个mysql容器 "mysql2", 通过 "-v" 来指定本地volume,实现与"mysql1_volume"数据共享
[vagrant@localhost ~]$ docker run -d -v mysql1_volume:/var/lib/mysql --name mysql2 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
0659f9dc97318a30da54fb150ee4587ca7f19a9b68fa2e07bfa7b47091f22c3a
[vagrant@localhost ~]$ docker volume ls
DRIVER VOLUME NAME
local mysql1_volume
[vagrant@localhost ~]$ docker exec -it mysql2 /bin/sh
# mysql -u root
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.13 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| docker |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.07 sec)
2.Bind Mouting
data volume 可以用于在容器运行过程中产生的一些数据,而我们想让这些数据在容器被删除时消失的场景
data volume 需要在 Dockerfile 中通过关键键字 "VOLUME" 来指定需要持久化数据的目录,而 bind mouting 不需要指定,直接通过 命令 "docker run -v 本地挂载目录:容器中持久化数据目录" 即可实现本地目录与容器中目录数据的同步,即本地目录中的数据做了修改则容器中对应的数据也将被修改.