Docker - 持久化存储和数据共享

Docker - Data Volume

想要了解Docker Volume,首先我们需要知道Docker的文件系统是如何工作的.Docker镜像是由多个文件系统(只读层)叠加而成.当我们启动一个容器的时候,Docker会加载镜像层并在其上添加一个读写层.如果运行中的容器修改了现有的一个已存在的文件,那该文件将会从读写层下的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏.当删除Docker容器,并通过该镜像重新启动时,之前的更改将会丢失.在Docker中,只读层以及在顶部的读写层的组合被称为Union FIle System(联合文件系统).为了能够保存(持久化)数据以及共享容器间的数据,Docker提出了Volume的概念.简单来说,Volume就是目录或者文件,它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上.

环境准备:

拉取MySQL的镜像:

1
docker pull mysql:latest

启动一个MySQL容器:

1
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
  • some-mysql: 容器别名
  • my-secret-pw:初始化设置的root用户的密码
  • tag:mysql的版本,不写默认使用最新版

参考:https://hub.docker.com/_/mysql/

创建一个Volume:

1
2
[vagrant@docker-host ~]$ docker run --name dk-mysql -v mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:latest
48a6888c4061c89f760685827e98955c8323747452c24deb1af688c2f56d38b6
  • -v : 指定MySQL的Volume路径以及名称

查看Volume:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[vagrant@docker-host ~]$ docker volume ls   # 查看当前机器上的Volume
DRIVER VOLUME NAME
local mysql

[vagrant@docker-host ~]$ docker volume inspect mysql # 查看volume的信息
[
{
"CreatedAt": "2018-06-15T16:23:27Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/mysql/_data",
"Name": "mysql",
"Options": null,
"Scope": "local"
}
]

可以看出Volume的数据的Mountpoint是存储在机器的/var/lib/docker/volumes/目录下。

测试Volume是否生效:

进入到MySQL容器中:

1
2
3
4
5
6
7
8
9
[vagrant@docker-host ~]$ docker exec -it dk-mysql /bin/sh
# mysql -u root -p # 进入到MySQL的shell中
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.≈≈≈≈
mysql> create database docker; # 创建数据库,名为docker
Query OK, 1 row affected (0.08 sec)
mysql> exit
Bye
# exit

强制删除容器:

1
2
3
4
5
6
7
[vagrant@docker-host ~]$ docker rm -f dk-mysql  # 强制删除MySQL容器
dk-mysql
[vagrant@docker-host ~]$ docker ps -a # 查看容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[vagrant@docker-host ~]$ docker volume ls # 查看volume mysql还在
DRIVER VOLUME NAME
local mysql

创建新容器使用旧的Volume:

1
2
[vagrant@docker-host ~]$ docker run --name mysql-new -v mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:latest  # 创建mysql容器 名为:mysql-new
9ab58b633584c5eab99cf28402dfdde22f349f79da9453115a8eab2cc41dc0bf

查看数据是否存在:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[vagrant@docker-host ~]$ docker exec -it mysql-new /bin/sh  # 进入到新的容器中
# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.

mysql> show databases; # 查看所有数据库 发现docker在列
+--------------------+
| Database |
+--------------------+
| docker |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)

Docker容器被删除之后Volume并不会被删除。

Docker - Bing Mounting:

环境准备:

在机器上创建一个目录,放一个html网页,然后将这个目录挂载到容器中:

1
2
3
4
5
[vagrant@docker-host ~]$ mkdir web && touch web/index.html
[vagrant@docker-host ~]$ vim web/index.html
[vagrant@docker-host ~]$ cd web/
[vagrant@docker-host web]$ more index.html
<h1>From Dokcer Container!</h1>

挂载目录到容器中:

将当前目录中的文件挂载到Nginx容器中:

1
[vagrant@docker-host web]$ docker run -d -p 8088:80 -v $(pwd):/usr/share/nginx/html  --name webnginx nginx
  • $(pwd): 当前目录

待容器启动后,可以访问容器:

1
http://192.168.10.10:8088/

容器中修改网页内容:

1
2
3
4
5
[vagrant@docker-host web]$ docker exec -it webnginx /bin/sh
# cd /usr/share/nginx/html
# vim index.html

<h1>From Dokcer Container! Edit</h1> # 修改完成后再次访问 可看到内容已更新

同样,在机器上修改文件,容器中的文件也会同步更新。

退出容器查看文件:

退出容器,查看机器上的文件,会发现已有变化:

1
2
[vagrant@docker-host web]$ more index.html
<h1>From Dokcer Container! Edit</h1>

Done.