• 文档:
  1. 【官方】Volumes - https://docs.docker.com/storage/volumes/
  • 更多:
  1. Docker的数据管理(volume/bind mount/tmpfs) - http://t.zoukankan.com/ExMan-p-11613073.html

docker 容器 mount失败_容器


文章目录

  • 容器与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 infoDocker 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