我们都知道每个容器都是独立的,那如果今天我想升级 MySQL 的版本,于是我把正在运行的
mysql:5.5
关闭,然后重新运行一个mysql:5.7
的容器,那数据库里面的数据不就消失了吗?
没错,这时候就需要 volume 了,简单来说 Volume 就是用来保存容器内的数据的,看看下面这张图
当你使用 volume 时,Docker 会在你的本地随机创建一个文件夹作为本地存储区域,大部分情况下会在 /var
下面,然后让这个文件夹与容器内的某个文件夹互通
由于它们是相互连接的,所以当您容器中的文件夹发生任何更改时,本地文件夹也会相应变化。而且非常重要的一点是:即使容器被删除,该文件夹仍将完整保留在原处。因此,我们可以利用这个特性来保留容器内的数据
实际操作
第一步 - 添加一个卷
我们新增了一个名为db-data的卷,完成后可以看到多了一个卷,此时Docker已经在本机上新增了一个文件夹供卷使用
> docker volume create --name db-data
> docker volume ls
第二步 - 使用volume
在启动时加一个 -v
参数,就可以指定 volume 要跟容器内哪一个文件夹连通,这边用的是 /db/data
,实际上使用时可以换成数据库存放数据的路径
demo 一下:
刚开始先确认一下里面什么文件都没有。
- 然后在容器内添加一个文件
file
- 最后再确认文件是否存在
> docker run -v db-data:/db/data -it ubuntu ls -la /db/data
> docker run -v db-data:/db/data -it ubuntu touch /db/data/file
> docker run -v db-data:/db/data -it ubuntu ls -la /db/data
值得注意的是,这三个指令运行在不同的容器中,这证明了当容器被关闭时,数据确实保存在卷内,并且下一个容器可以成功读取上一个容器留下的数据
主机容量
上面提到的那种先创建再使用的卷被称为命名卷,现在要介绍另外一种叫做主机卷的方式,用来直接指定主机上的某个文件夹与容器内的文件夹相连
来一段演示:
1.检查 ~/app
内没有 package.json
2.将本机的 ~/app
与容器内的 /app
连接起来,然后在容器内运行 npm init
。
3.跑完后再回到本机确认是否已经生成 package.json
> ls -la app
> docker run -v ~/app:/app --workdir /app node:slim npm init -y
> ls -la app
在上面的例子中,实际上 package.json
是在容器内生成的,因此一旦有了volume,就可以不必安装yarn,但仍然可以运行 yarn init
同样的道理,你甚至可以在不安装编译器的情况下编译C++源代码,也可以在不安装JDK的情况下开发Java程序,甚至可以在不安装MongoDB的情况下使用它来存储数据。只需在电脑上安装一个Docker,真是太神奇了🎉🎉