- 文档:
- 【官方】Volumes - https://docs.docker.com/storage/volumes/
- 更多:
- Docker的数据管理(volume/bind mount/tmpfs) - http://t.zoukankan.com/ExMan-p-11613073.html
文章目录
- 容器与host之间共享
- 存储设备 storage driver
- 数据卷 data volume
- bind mount
- 坑: --mount 参数
- docker managed volume ⭐️
- 坑: 清理docker中没有被使用数据卷(volume)
- 坑: --mount 参数
- 备份、恢复、前移
- tmpfs mounts (非持久化存储)
- 容器与容器间共享
- 卷容器 volume container
- 数据打包卷容器 data-packed volume container
容器与host之间共享
docker存储有两种:storage driver 和 data volume
存储设备 storage driver
storage driver 是由镜像层和容器层组成的,可以通过 docker inspect <容器ID>
来查看容器默认使用的 driver
优先使用Linux发行版默认的storage driver,其具有最好的稳定性
对于没有需要持久化的数据的无状态的容器,可以直接将数据放在由storage driver维护的层中
数据卷 data volume
data volume 又分为两种 bind mount 和 docker managed volume
先给出总结:
- bind mount
宿主有数据时,数据以宿主机为准
宿主无数据时,数据以宿主机为准(空文件夹覆盖从容器文件夹) - volume
宿主有数据时,数据以宿主机为准
宿主无数据时,复制从容器数据进入宿主机数据卷,再以宿主机数据卷数据为准
| bind mount | docker managed volume |
volume 位置 可任意指定 | /var/lib/docker/volumes/… | |
对已有mount point影响 | 隐藏并替换为volume | 原有数据复制到volume |
是否支持单个文件 | 支持 | 不支持,只能是目录 |
权限控制 | 可设置为只读,默认为读写权限 |
同样可以设置只读 |
移植性 | 移植性弱,与host path绑定 | 移植性强,无需指定host目录 |
下面具体介绍:
bind mount
bind mount: 将host上已存在的目录或文件mount到容器
例如:
# 读写
docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs:rw httpd
# 只读
docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs:ro httpd
🚨 注意
- 左边指定的必须是宿主机系统文件路径,限制了移植性(没有相应路径就报错)
- 如果宿主机文件夹内没有数据,从容器文件夹中有数据,且需要这些数据,那么直接挂载后,从容器会报错。
这时候需要先把数据从从容器中复制到宿主机文件夹内,再进行挂载。(非常麻烦)
通过 inspect 可以查看容器挂载的数据卷类型
$ sudo docker inspect myhalo
...
"Mounts": [
{
"Type": "bind", // <------------------------- 类型是 bind
"Source": "/volume1/server/halo/.halo",
"Destination": "/root/.halo",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind", // <------------------------- 类型是 bind
"Source": "/volume1/server/halo/halojar",
"Destination": "/root/appjar",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
...
坑: --mount 参数
同样功能,可以用–mount实现
使用–mount参数时,需要指定type=bind:
$ docker run -d \
--name=nginxtest \
--mount type=bind,source=/usr/local/web,destination=/usr/share/nginx/html \
nginx:latest
# 等同
$ docker run -d \
--name=nginxtest \
-v /usr/local/web:/usr/share/nginx/html \
nginx:latest
docker managed volume ⭐️
docker managed volume: 是在容器启动的时候会在 host 的 /var/lib/docker/volume/***/_data
自动创建一个 bind mount 并将容器中相应的内容复制一份到 /var/lib/docker/volume/***/_data
下
格式为:
# 指定卷名,方便日后管理
docker -v <volume name>:<container path>
# 不指定卷名,docker自动生成一串hash值,非常不好日后查看
docker -v <container path>
💡 提示
docker 数据卷默认的存储位置是
var/lib/docker/
,但是,可以通过编辑 docker.conf 文件更改(不同系统,流程各异,目的是更改--graph=/var/lib/docker
参数)我们可以通过
docker info
的Docker Root Dir
项查看具体位置:$ sudo docker info | grep 'Docker Root Dir' Docker Root Dir: /volume1/@docker
坑: 清理docker中没有被使用数据卷(volume)
如果,使用docker管理的volume可以很方便的创建数据卷。但是,当容器被删除后,数据卷还是会保留的(因为,docker不清楚这个数据卷你是否还有用)。
如果数据卷确实不会再次挂载,这就需要我们手动去清理。(因为是会占用内存的)
查看数据卷占用的内存:
$ sudo docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 6 2 2.642GB 1.766GB (66%)
Containers 2 2 9.39MB 0B (0%)
Local Volumes 41 0 2.574GB 2.574GB (100%) <---- 这里
Build Cache 0 0 0B 0B
查看全部数据卷 docker volume ls
。
💡 提示
我们确实可以通过对比
docker inspect <container id>
的挂载情况,确定哪些数据卷是没用的,然后用docuer volume rm <volume id>
物理删除数据卷。
但是,这太反人类了,后面可以使用sudo docker volume prune
命令一键删除没有被使用的数据卷💡 提示
批量删除孤儿volume
- 新
docker volume prune
- 旧
docker volume rm $(docker volume ls -q)
$ sudo docker volume
Password:
Usage: docker volume COMMAND
Manage volumes
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused local volumes
rm Remove one or more volumes
Run 'docker volume COMMAND --help' for more information on a command.
$ sudo docker volume ls
DRIVER VOLUME NAME
local 1a489a17e925d54e53e982e2ab5e38fddeede268d4d6630ed3d9591aa93d2708
local 1c851a1e8019a3629b8bc64e89a4048b56d6810a9c79e701788380b58577bd5f
local 3ab193c091c09ed468cec1a5f0581d9ac02323250d824afc69ff54c5c47e3514
local 3ba33f6f3635d43a732294eb360ca228bc62b20d56525ec36e51abdbc2f2a086
local 05dd739c188f800265a96b2a8344344558b983729a052fd72433e8dfa08f36bd
local 7d8b35c58b0f6e92318cb50b420234e9c9a59115348fd13c25ad48a994002928
local 7d42fc870ef0230de17e8b0beb7650e06e159bd3703a5be7c5ff376a33e17beb
local 8c12da75772180a10f8c621c228cf226eff6508fecd34781d8ef5034bc009a90
local 9b60f592d8f6796b56d4dbfdb9cd8e85d6d0d4fce716bba522a42543c3915de7
local 14cfdf3f4eb7639004d1b45be8c5e4ff62da87a5be0da731154ef29e9e35d2e4
local 16d384553cd2c71c907dccbdccf30024b3510e9d174d81eeca979c1b3447233f
local 26a2eadc82af3b62988f7846abe11a4ab1980f8261ae61a88ff2684755d7763d
local 34a9702b2e8b617bca7bd38afec393708b07579c34871231a1dede622ec164f7
local 48cb5985a81d8ef354e7343db3378c9367c918cfe57f0383e9ccf42f35ccb499
local 64e74ea9131dbf4c17f095d78f2021ad86489a729755d8a00c2b6bf3377c5085
local 142b8e9be61aebd1afda45784582ec20e0c2842edf3a30e3a65a00658b36cdf5
local 510d4ae2fb9387108f5d1d6fe329511243ffbb20f458d9edd551fb6824a38038
local 659a7bd77f0ab7df419a8354b2c0136708f511088b94026df27d3584ef26af42
local 789db00f357c360fe8867a7df12b43120ca58a213eee3afa0cca549253109023
local 925bb66c6ecd9ecd7340f3882ce18c7df3d3acaad376ad0dc644090f3f65a3bb
local 1831cdb55a1cf1194e12dc02a9473db2b4bda06b8829b2b8d9507857396bfa99
local 7957deb0ce7dc99311a3e292ec6c4b7f115c772c58220ff7d86d1a824e8d0cad
local 9893fbf96b767ce0769b9c44c3aa9c2e410272d17e822d33676e1554e5ab28e5
local 29584fcea3f2012a3be6a47b503cb83a853f4d26f3b799109ad712fb322448ff
local 55411a0e01bb22773e3c70ec9f2b234b0260ac4fc74c0ad858dcc92f76aab8b2
local 78029a7b1348a9d404648f258773047f9bed2c9edb2c52613837c546f8b643ae
local 181384d2ebc18222957347ecb2ed21bd5e87249de17054ed878f99e0ba9decd7
local 7318637d1efba7b6ef0fac08d78a5f87c97b1b4c202e4b92ccacd4c907826399
local 8787750bf1669657964393e7e0fc9225e71178d989447d36f6d81579c85a06ba
local 68172165d93a13f33f5dc781f661ce137250fe4c5b2234010afd7e0bf7dedf02
local a1899b40493d58bd18ff89b34f05777434dfeede8c2edf2b402774b5a42d42c4
local ae633ae27180d6509c0123f2e5b56c433bce7d2223b1354dabb79d2dec484bcc
local b3ff5fc7883d093907a3afaa37a74677cc1a85e8aa1e394fb66b2ed3e6a01226
local b5aea2219ee1652045b6c7c640d69df14a6df4030ef1d137741cadcae4bcee84
local b36b54be0f0721becd52520619a861c4ce8cce7664108f23a6ae7cdb7996a334
local bed5d5019dbb6e8f3c7baa746f21a8d267af623f7dd5b0d6ff0bf3fdba7d120e
local c62fac460747eaf9127cc936ac5a7364f4d41083080acf52095b196fce67f418
local cf179b0af92b620de91d81fe852892aa4b2ac0e156767a733feb899667e8c0c5
local d7252c604093feba672b8db8e628a97776f5cd4e619968e2a1af9e88aa469357
local e643929b87c2efdb58a9d2a9e6eb330b9036b91be21d2af5db365f1c090e384a
local fe0ff84ffd2de471fbda3da31d00e1786b1e181f80bae09d7e99f75842bce548
使用命令,会警告你,问你是否确定删除数据卷。
(硬盘容量用钱买,数据买不了。数据很重要!!)
$ sudo docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
26a2eadc82af3b62988f7846abe11a4ab1980f8261ae61a88ff2684755d7763d
142b8e9be61aebd1afda45784582ec20e0c2842edf3a30e3a65a00658b36cdf5
16d384553cd2c71c907dccbdccf30024b3510e9d174d81eeca979c1b3447233f
b5aea2219ee1652045b6c7c640d69df14a6df4030ef1d137741cadcae4bcee84
3ab193c091c09ed468cec1a5f0581d9ac02323250d824afc69ff54c5c47e3514
68172165d93a13f33f5dc781f661ce137250fe4c5b2234010afd7e0bf7dedf02
9b60f592d8f6796b56d4dbfdb9cd8e85d6d0d4fce716bba522a42543c3915de7
14cfdf3f4eb7639004d1b45be8c5e4ff62da87a5be0da731154ef29e9e35d2e4
fe0ff84ffd2de471fbda3da31d00e1786b1e181f80bae09d7e99f75842bce548
ae633ae27180d6509c0123f2e5b56c433bce7d2223b1354dabb79d2dec484bcc
181384d2ebc18222957347ecb2ed21bd5e87249de17054ed878f99e0ba9decd7
c62fac460747eaf9127cc936ac5a7364f4d41083080acf52095b196fce67f418
7d42fc870ef0230de17e8b0beb7650e06e159bd3703a5be7c5ff376a33e17beb
8787750bf1669657964393e7e0fc9225e71178d989447d36f6d81579c85a06ba
8c12da75772180a10f8c621c228cf226eff6508fecd34781d8ef5034bc009a90
925bb66c6ecd9ecd7340f3882ce18c7df3d3acaad376ad0dc644090f3f65a3bb
e643929b87c2efdb58a9d2a9e6eb330b9036b91be21d2af5db365f1c090e384a
659a7bd77f0ab7df419a8354b2c0136708f511088b94026df27d3584ef26af42
1c851a1e8019a3629b8bc64e89a4048b56d6810a9c79e701788380b58577bd5f
55411a0e01bb22773e3c70ec9f2b234b0260ac4fc74c0ad858dcc92f76aab8b2
48cb5985a81d8ef354e7343db3378c9367c918cfe57f0383e9ccf42f35ccb499
b36b54be0f0721becd52520619a861c4ce8cce7664108f23a6ae7cdb7996a334
3ba33f6f3635d43a732294eb360ca228bc62b20d56525ec36e51abdbc2f2a086
b3ff5fc7883d093907a3afaa37a74677cc1a85e8aa1e394fb66b2ed3e6a01226
1831cdb55a1cf1194e12dc02a9473db2b4bda06b8829b2b8d9507857396bfa99
64e74ea9131dbf4c17f095d78f2021ad86489a729755d8a00c2b6bf3377c5085
7d8b35c58b0f6e92318cb50b420234e9c9a59115348fd13c25ad48a994002928
78029a7b1348a9d404648f258773047f9bed2c9edb2c52613837c546f8b643ae
d7252c604093feba672b8db8e628a97776f5cd4e619968e2a1af9e88aa469357
05dd739c188f800265a96b2a8344344558b983729a052fd72433e8dfa08f36bd
34a9702b2e8b617bca7bd38afec393708b07579c34871231a1dede622ec164f7
cf179b0af92b620de91d81fe852892aa4b2ac0e156767a733feb899667e8c0c5
bed5d5019dbb6e8f3c7baa746f21a8d267af623f7dd5b0d6ff0bf3fdba7d120e
7318637d1efba7b6ef0fac08d78a5f87c97b1b4c202e4b92ccacd4c907826399
a1899b40493d58bd18ff89b34f05777434dfeede8c2edf2b402774b5a42d42c4
1a489a17e925d54e53e982e2ab5e38fddeede268d4d6630ed3d9591aa93d2708
510d4ae2fb9387108f5d1d6fe329511243ffbb20f458d9edd551fb6824a38038
789db00f357c360fe8867a7df12b43120ca58a213eee3afa0cca549253109023
9893fbf96b767ce0769b9c44c3aa9c2e410272d17e822d33676e1554e5ab28e5
29584fcea3f2012a3be6a47b503cb83a853f4d26f3b799109ad712fb322448ff
7957deb0ce7dc99311a3e292ec6c4b7f115c772c58220ff7d86d1a824e8d0cad
Total reclaimed space: 2.574GB
查看删除后的情况
$ sudo docker volume ls
DRIVER VOLUME NAME
$ sudo docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 6 2 2.642GB 1.766GB (66%)
Containers 2 2 9.39MB 0B (0%)
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0B
坑: --mount 参数
同样的挂载功能,也可以使用 --mount
实现
# 创建一个Volume
$ docker volume create my-vol
# 查看Volumes
$ docker volume ls
local my-vol
$ docker volume inspect my-vol
[
{
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
"Name": "my-vol",
"Options": {},
"Scope": "local"
}
]
# 挂载数据卷到容器目录
## 使用--mount参数
$ docker run -d \
--name=nginxtest \
--mount source=nginx-vol,destination=/usr/share/nginx/html \
nginx:latest
## 使用 -v 参数
### 1. -v 参数使用冒号分割 source 和 destination,冒号前半部分是 source,后半部分是 destination
### 2. 如果你挂载一个还不存在的数据卷,Docker 会自动创建它。(因此创建数据卷那一步非必需)
### 3. 如果容器中的待挂载的目录不是一个空目录,那么该目录下的文件会被复制到数据卷中。(Bind mounts下,宿主机上的目录总会覆盖容器中的待挂载目录)
$ docker run -d \
--name=nginxtest \
-v nginx-vol:/usr/share/nginx/html \
nginx:latest
💡 提示
-v 参数和 --mount 参数总的来说功能几乎相同,唯一的区别是在运行一个 service 时只能够 --mount 参数来挂载数据卷。
备份、恢复、前移
# 💡先建立一个容器vol_simple,该容器在/date挂载了一个volume。
$ sudo docker run -it --name vol_simple -v /data ubuntu /bin/bash
# 💡备份
# ❌方法一:
# 使用docker inspect命令查找/date在宿主机上对应的文件夹位置,然后复制其中内容或是使用tar进行打包。
# 同样如果需要恢复某个volume中的数据,可以查找到volume对应的文件夹,将数据复制进这个文件夹或者使用tar恢复。
# 🔥这些笨拙的做法并不值得推荐,因为查找主机上文件夹后在再操作容易出错,也不适合脚本的自动化。
# ✔️方法二:
# 备份volume可以使用以下方法。
$ sudo docker run --rm \
--vloumes-from vol_simple \
-v $(pwd):/backup \
ubuntu \
tar cvf /backup/data.tar /data
# 🔥这个指令启动了一个临时的容器,这个容器挂载了两个volume
# 1. 第一个volume与要备份的volume共享
# 2. 第二个volume将宿主机的当前目录挂载到容器的/backup下
# 容器运行后,将要备份的内容(/data文件夹)备份到/backup/data.tar,然后删除容器
# 备份后的data.tar就留在了当前目录。
# 💡恢复
# 1. 创建容器
$ sudo docker run -it --name vol_bck -v /data ubuntu /bin/bash
# 2. 复制、解压
$ sudo docker run --rm \
--volumes-from vol_bck \
-v $(pwd):/backup \
ubuntu \
tar xvf /backup/data.tar -C /
tmpfs mounts (非持久化存储)
tmpfs mounts,顾名思义,是一种非持久化的数据存储。它仅仅将数据保存在宿主机的内存中,一旦容器停止运行,tmpfs mounts会被移除,从而造成数据丢失。
我们可以在运行容器时通过指定–tmpfs参数或–mount参数来使用tmpfs mounts:
$ docker run -d \
-it \
--name tmptest \
--mount type=tmpfs,destination=/app \
nginx:latest
$ docker run -d \
-it \
--name tmptest \
--tmpfs /app \
nginx:latest
使用–tmpfs参数无法指定任何其他的可选项,并且不能用于Swarm Service。
使用docker container inspect tmptest命令,然后查看Mounts部分可以看到:
"Tmpfs": {
"/app": ""
},
tmpfs mounts 可选选项:
option | description |
tmpfs-szie | 挂载的tmpfs的字节数,默认不受限制 |
tmpfs-mode | tmpfs的文件模式,例如700或1700,默认1777,这意味着任何用户都有权读写 |
一个例子:
docker run -d \
-it \
--name tmptest \
--mount type=tmpfs,destination=/app,tmpfs-mode=1770 \
nginx:latest
容器与容器间共享
卷容器 volume container
volume container是专门为其他容器提供volume的容器
其他容器通过–volumes-from 来挂载这个容器
$ docker create --name vc_data -v ~/htdocs:/usr/local/apache2/htdocs -v /other/useful/tools busybox
$ docker run -d -p 80 --volumes-from vc_data httpd
数据打包卷容器 data-packed volume container
data-packed volume container:
将数据打包到镜像中,然后通过docker managed volume共享
是通过创建挂载的镜像,这种方式移植性特别强,但是无法动态修改共享文件
Dockerfile:
FROM busybox:latest
ADD htdocs /usr/local/apache2/htdocs
VOLUME /usr/local/apache2/htdocs
docker build -t datapacked
docker create --name vc_data datapacked