Docker存储卷(V18.X)
简介
介绍
Docker的存储卷称之为volume,本质上容器上的一个或者多个目录,而这些目录绕过了联合文件系统,与宿主机中的目录或者其他容器目录进行了绑定关系,这种绑定关系可以看作Linux的mount操作,当容器中的程序对这些目录写入数据时,其实写入到的是与之绑定的宿主机目录上,这样就实现了数据的存储功能。特别说明:本文章所使用的docker版本基于v18.X,对于较早版本的docker并不适合,例如tmpfs类型卷是v17.06新加入的存储卷。
作用
默认情况下,容器不使用任何 volume时,容器的数据被保存在容器之内,它只在容器的生命周期内存在,会随着容器的删除而被删除,而想要持久化的存储这些数据,就得使用存储卷。特别的,保存容器中的数据也可以使用 docker commit 命令将容器提交为一个新的镜像,这个镜像中会保存容器运行时的所有数据(绑定的数据卷除外),但此种方法非常不推荐,因为这样的镜像通常会很大,镜像拉取以及运行容器都会变慢。当容器使用了存储卷,即使容器被删除了,但是与绑定的存储卷还在,对应目录的数据都会保存,如果想要恢复该容器,只要新建的容器绑定该存储卷,对应目录的数据也会随之恢复。
分类
Docker存储卷可分为两类:
- Volumes:数据卷,这类存储卷是被Docker Daemon管理,可使用docker volume create显示创建,被创建出来的卷位于/var/lib/docker/volumes/下,使用时候只需指定使用卷的名称以及对应的容器的一个目录,删除时候只需指定删除卷名即可,这类数据卷是存储数据最为推荐的方式。
- Bind mounts :绑定挂载卷,从早版本docker提供,这类存储卷可以是宿主机的任意目录,也可以是来自其他容器的目录,不受docker Daemon管理,删除时候需要手动清理目录。
- tmpfs mounts:临时挂载卷,该类存储卷数据存放在主机内存中,好处在于这类存储卷由于使用的tmpfs格式文件系统,读写性能好,但同时也增加了主机的内存开销,Docker早期版本不支持此类存储卷。
以下是其示意图:
存储卷使用
--volume&&--mount
存储卷的使用是在docker run命令时候使用-v或者--volume来指明使用的存储卷,但是如果需要指明更多选项如卷类型、驱动等那就需要使用--mount来指明更多的选项。以下是两种选择的使用方法。
-v或--volume选项:[volume_name]:container_path:[options]
解释:
由三个字段组成,用冒号字符(:)分隔,字段必须按正确的顺序排列
volume_name:卷名,可省略,省略的时候默认会分配一个随机目录,在/var/lib/docker/volumes/随机目录/_data。还可以指定宿主机目录。
container_path:绑定的容器中的目录,必须。
options:其他选项,是逗号分隔的选项列表,例如读写模式(ro、rw),可省略。
示例:创建一个绑定挂载卷
--mount:该选项从V17.06加入,由多个键值对组成,用逗号分隔,每个键值由<key>=<value>组成。常用的key如下:
- type:指明卷的类型,三种类型之一bind、volume、tmpfs
- source:可简写为src,指定挂载来源通常是卷名称,匿名卷时忽略该选项
- destination:可简写为dst或target,指定容器中的使用的目录
- readonly:指定卷是否为只读
- volume-opt:其他挂载选项可以多次使用,采用volume-opt=type=nfs
示例:将上述容器使用--mount启动(这里换一个名称为nginx-c2):
使用建议:两个命令能都实现数据卷的挂载,如果是老用户可以继续使用-v的方式来运行容器,如果是新用户推荐使用--mount,这样的语法比较简介明了,比如人性化的各种选项src、type、dest,但是如果需要使用tmpfs类型的数据卷时候必须使用--mount。
使用Volumes
volume类型的数据卷是比较推荐方式,它是能被Docker 管理的卷, 使用流程是先创建卷,在使用-v或--mount进行挂载。如果在docker run时候不指定其宿主机目录,则默认也属于volumes类型,也受Docker管理。
创建卷
[root@app51 ~]# docker volume create data-vol
data-vol
[root@app51 ~]# docker volume inspect data-vol
[
{
"CreatedAt": "2019-02-28T17:39:36+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/data-vol/_data",
"Name": "data-vol",
"Options": {},
"Scope": "local"
}
]
[root@app51 ~]#
挂载卷并写入数据
[root@app51 ~]# docker run -it --name bs1 -v data-vol:/data/tmp busybox:latest /bin/sh
/ # ls /data/tmp/
/ # echo "hello world" > /data/tmp/index.html
/ #
在宿主机上查看:
创建卷是还可以指定其他,列如指定大小、uid等其他选项,这些选项都是mount命令的选项,卷的管理中会介绍:
[root@app51 ~]# docker volume create --driver local --opt type=tmpfs --opt device=tmpfs --opt o=size=100m,uid=1000 test-vol6
test-vol6
[root@app51 ~]# docker run -it --name bs6 -v test-vol6:/data/tmp busybox:latest /bin/sh
/ # ls /data
tmp
上面的挂载命令使用等价--mount:
[root@app51 ~]# docker run -it --name bs7 --mount type=volume,src=test-vol6,dst=/data/tmp busybox:latest /bin/sh
/ #
容器内可以使用mount命令可以查看挂载点:
使用bind mounts
绑定挂载卷使用,无非指定宿主机的具体某个目录,可以使用-v HOST_PATH:CONTAINER_PATH 也可以使用--mount type=bind,src=HOST_PATH,dst=CONTAINER_PATH。
示例:
[root@app51 ~]# docker run -it --name bind-vol -v "$(pwd)":/data busybox:latest /bin/sh
/ # ls /data
Dockerfile a.txt anaconda-ks.cfg dr.sh nat.sh nginx-bus.tar.gz nginx.tar
/ #
等价于使用--mount:
[root@app51 ~]# docker run -it --name bind-vol-1 --mount type=bind,src="$(pwd)",dst=/data busybox:latest /bin/sh
/ # ls /data
Dockerfile a.txt anaconda-ks.cfg dr.sh nat.sh nginx-bus.tar.gz nginx.tar
/ #
以只读的方式挂载:
[root@app51 ~]# docker run -it --name bind-vol-2 --mount type=bind,src="$(pwd)",dst=/data,readonly busybox:latest /bin/sh
/ # ls /data/
Dockerfile a.txt anaconda-ks.cfg dr.sh nat.sh nginx-bus.tar.gz nginx.tar
/ # cd /data/
/data # touch 1.txt
touch: 1.txt: Read-only file system
/data #
查看卷(新开终端):
[root@app51 ~]# docker inspect bind-vol-2 "Mounts": [
{
"Type": "bind",
"Source": "/root",
"Target": "/data",
"ReadOnly": true
}
],
使用tmpfs mounts
tmpfs类型的卷只适用于Linux系统,命令行中除了使用--mount指定外还可以使用--tmpfs指定其类型。特别注意的,与volume卷和绑定挂载卷相反,tmpfs挂载是临时的,并且仅在主机内存中持久存在,当容器停止时,将删除tmpfs挂载,并且不会保留写在那里的文件。
示例 使用--mount:
[root@app51 ~]# docker run -it --name tmpfs-c1 --mount type=tmpfs,dst=/app busybox:latest /bin/sh
/ #
/ # mount |grep /app
tmpfs on /app type tmpfs (rw,nosuid,nodev,noexec,relatime)
等价于使用--tmpfs:
[root@app51 ~]# docker run -it --name tmpfs-c2 --tmpfs /app busybox:latest /bin/sh
/ # mount |grep /app
tmpfs on /app type tmpfs (rw,nosuid,nodev,noexec,relatime)
/ #
查看挂载卷:
[root@app51 ~]# docker inspect tmpfs-c1 "Mounts": [
{
"Type": "tmpfs",
"Source": "",
"Destination": "/app",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
注意--mount选项还支持指定挂载目录的大小和权限,选项如下:
tmpfs-size | 设置tmpfs类型卷的大小,默认无限制(即由宿主机内存决定) |
tmpfs-mode | 设置tmpfs类型卷挂载的目录权限,如1770。默认1777 |
指定一个大小为50m,目录选项为1770类似为tmpfs的存储卷:
[root@app51 ~]# docker run -it --name tmpfs-c3 --mount type=tmpfs,dst=/data/tmp,tmpfs-mode=1770,tmpfs-size=50m busybox:latest /bin/sh
/ #
/ #
/ # mo
modinfo modprobe more mount mountpoint
/ # mount |grep /data/tmp
tmpfs on /data/tmp type tmpfs (rw,nosuid,nodev,noexec,relatime,size=51200k,mode=1770)
/ # ls /data/ -l
total 0
drwxrwx--T 2 root root 40 Mar 1 01:47 tmp
查看其存储卷信息:
[root@app51 ~]# docker inspect tmpfs-c3 "Mounts": [
{
"Type": "tmpfs",
"Source": "",
"Destination": "/data/tmp",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
使用容器数据卷
除了以上数据卷外,还可以直接使用容器中已经挂载的数据卷,使用--volumes-from指定,此时两个容器的数据卷是共享的。从本质上来讲,这两数据卷共同挂载了宿主机上的同一个目录。
示例:创建一个容器share-c1挂载当前目录(确保不要退出)
[root@app51 ~]# docker run -it --name share-c1 -v $(pwd):/data busybox:latest /bin/sh
/ # ls /data/
Dockerfile a.txt anaconda-ks.cfg backup.tar dr.sh nat.sh nginx-bus.tar.gz nginx.tar
/ #
在运行一个容器挂载share-c1的卷:
[root@app51 ~]# docker run -it --name share-c2 --volumes-from share-c1 busybox:latest /bin/sh
/ # ls /data/
Dockerfile a.txt anaconda-ks.cfg backup.tar dr.sh nat.sh nginx-bus.tar.gz nginx.tar
/ #
存储卷管理
docker存储卷管理通过docker volume命令组实现,v18.09的命令集合如下:
1.创建存储卷
docker volume create [OPTIONS] [VOLUME_NAME]
通常这样创建的卷会保存在宿主机目录/var/lib/docker/volumes/VOLUME_NAME/_data如果不指名 VOLUME则会创建匿名卷,方式等同于在docker run -v不指定宿主机目录。
常用选项:
-o, --opt :指定存储卷挂载选项。常用选项如下:
- type: 挂载文件系统类型,可以是tmpfs、brtfs、甚至是nfs。
- device:挂载的设备,
- o:mount命令挂载选项,其选项可参考这里
示例一:创建一个普通的卷名称为test-vol-1。
[root@app51 test-vol-1]# docker volume create test-vol-1
test-vol-1
[root@app51 test-vol-1]# ls /var/
adm/ crash/ empty/ gopher/ lib/ lock/ mail/ opt/ run/ tmp/ yp/
cache/ db/ games/ kerberos/ local/ log/ nis/ preserve/ spool/ .updated
[root@app51 test-vol-1]# ls /var/lib/docker/volumes/test-vol-1/ -l
总用量 0
drwxr-xr-x 2 root root 6 3月 1 11:08 _data
[root@app51 test-vol-1]#
示例二:创建一个tmpfs类型的存储卷,名称为test-vol-2
[root@app51 test-vol-1]# docker volume create --opt type=tmpfs --opt device=tmpfs --opt o=size=100m,uid=1000 test-vol-2
test-vol-2 ###挂载test-vol-2
[root@app51 test-vol-1]# docker run -it --name bs-c10 -v test-vol-2:/data busybox:latest /bin/sh
/ # mount |grep /data
tmpfs on /data type tmpfs (rw,relatime,size=102400k,uid=1000)
/ #
示例三:创建一个nfs类型的存储卷,服务器地址为10.1.210.52,权限读写,目录为/data/tmp,名称为test-vol-3
[root@app51 test-vol-1]# docker volume create --opt type=nfs --opt o=addr=10.1.210.52,rw --opt device=:/data/tmp test-vol-3
test-vol-3
需要注意的是:创建的卷即使创建成功了但是挂载的时候很可能出错,docker不会在创建卷时候检查挂载选项是否符合要求。
2.查看存储卷详情
docker volume inspect [OPTIONS] VOLUME [VOLUME...]
常用选项:
-f, --format :输出格式,基于go模版
示例:
[root@app51 ~]# docker inspect test-vol-1
[
{
"CreatedAt": "2019-03-01T11:08:00+08:00",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/test-vol-1/_data",
"Name": "test-vol-1",
"Options": {},
"Scope": "local"
}
]
使用-f:.代表以根开头,Name是一级字段。
[root@app51 ~]# docker inspect test-vol-1 -f {{.Name}}
test-vol-1
[root@app51 ~]#
3.查看所有存储卷
docker volume ls [OPTIONS]
常用选项:
-f, --filter 过滤具体存储卷
示例:
[root@app51 ~]# docker volume ls
DRIVER VOLUME NAME
local test-vol-1
local test-vol-2
local test-vol-3
[root@app51 ~]#
过滤某个卷:
[root@app51 ~]# docker volume ls -f name=test-vol-1
DRIVER VOLUME NAME
local test-vol-1
4.删除一个或多个卷
docker volume rm [OPTIONS] VOLUME [VOLUME...]
常用选项:
-f, --force 强制删除存储卷,即使它还在被使用
[root@app51 ~]# docker volume ls
DRIVER VOLUME NAME
local test-vol-1
local test-vol-2
local test-vol-3
[root@app51 ~]# docker volume rm test-vol-3
test-vol-3
[root@app51 ~]# docker volume ls
DRIVER VOLUME NAME
local test-vol-1
local test-vol-2
[root@app51 ~]#
5.移除本地未使用的卷
docker volume prune [OPTIONS]
[root@app51 ~]# 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:
test-vol-1 Total reclaimed space: 0B
[root@app51 ~]#
数据卷的备份与恢复
数据备份
容器中的数据卷备份有两种方式,一是你可以直接备份与之对应的宿主机目录,二则运行一个容器挂载有数据的容器将其备份到与之对应的宿主机目录。这里演示下第二种数据备份方法。
方法:
1.创建备份容器并挂载需要备份的目录,同时挂载宿主机目录进行备份任务。
2.运行备份指令并将备份数据放到挂载的宿主机目录,以下示例为/backup,将数据备份在来/backup就等于备份在了宿主机的$(pwd)目录下,也就是当前目录。
新建一个数据容器并写入数据:
[root@app51 ~]# docker run -it --name data-c1 -v /data busybox:latest /bin/sh
/ # cd /data/
/data # touch 1.txt
/data # echo "hello world" > index.html
/data # ls -l
total 4
-rw-r--r-- 1 root root 0 Mar 1 07:40 1.txt
-rw-r--r-- 1 root root 12 Mar 1 07:40 index.html
/data #
创建备份容器同时挂载两个目录进行数据备份:
[root@app51 ~]# docker run --rm --volumes-from data-c1 -v $(pwd):/backup centos tar cvf /backup/backup.tar /data
/data/
/data/1.txt
/data/index.html
tar: Removing leading `/' from member names
查看备份数据:
[root@app51 ~]# ls -l
总用量 220332
-rw-------. 1 root root 1258 1月 16 00:15 anaconda-ks.cfg
-rw-r--r-- 1 root root 7 2月 27 10:25 a.txt
-rw-r--r-- 1 root root 10240 3月 1 15:42 backup.tar
-rw-r--r-- 1 root root 76 2月 27 19:14 Dockerfile
-rw-r--r-- 1 root root 578 1月 16 10:41 dr.sh
-rw-r--r-- 1 root root 559 1月 16 14:53 nat.sh
-rw------- 1 root root 114356736 2月 24 10:56 nginx-bus.tar.gz
-rw------- 1 root root 111224320 2月 23 19:18 nginx.tar
[root@app51 ~]# tar tvf backup.tar
drwxr-xr-x root/root 0 2019-03-01 15:40 data/
-rw-r--r-- root/root 0 2019-03-01 15:40 data/1.txt
-rw-r--r-- root/root 12 2019-03-01 15:40 data/index.html
数据恢复
恢复数据的原理与备份类似,也是启动一个容器共享需要备份的目录,同时挂载宿主机的备份目录,最后解压数据到备份目录中。为了演示数据恢复,我将上述容器 data-c1中的data目录中文件全部删除:
[root@app51 ~]# docker run -it --name data-c1 -v /data busybox:latest /bin/sh
/ # cd /data/
/data # rm -rf *
/data #
创建一个恢复容器:
[root@app51 ~]# docker run --rm --volumes-from data-c1 -v $(pwd):/backup centos bash -c "cd / && tar xvf /backup/backup.tar"
data/
data/1.txt
data/index.html
[root@app51 ~]#
再次查看data-c1容器数据:
/data # rm -rf data
/data #
/data #
/data #
/data #
/data # ls -l
total 4
-rw-r--r-- 1 root root 0 Mar 1 07:40 1.txt
-rw-r--r-- 1 root root 12 Mar 1 07:40 index.html
/data #
Docker存储卷(V18.X)的更多相关文章
- Docker系列05—Docker 存储卷详解
本文收录在容器技术学习系列文章总目录 1.存储卷介绍 1.1 背景 (1)docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加面成,启动容器时,docker会加载只读镜像层并在镜 ...
- 6、Docker存储卷
Why Data Volumes? 来自马哥教育 Data volumes Volume types 绑定挂载卷:在宿主机和容器上各指明绑定路径才能进行绑定. docker管理卷:在容器内指定挂载 ...
- Docker存储卷
六.Docker 存储卷(volume) COW:写时复制 Bind mount volume:手动mount绑定的卷 # docker run --name centos-3 -it -v /dat ...
- docker 存储卷 Volumes
一,docker容器面临的困境: 容器运行中产生的数据,是放到容器栈的最顶层,当容器停止并被删除后,这些数据就被删除了. docker采用COW(写时复制)策略,导致性能低下.比如有个mysql容器, ...
- Docker存储卷篇
Docker存储卷篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.写时复制(COW)机制 所谓写时复制的效果如上图所示: Docker镜像由多个只读层叠加而成,启动容器 ...
- Docker 学习6 Docker存储卷
一.什么是存储卷 二.为什么要用到数据卷 三.数据卷是怎么被管理的 四.存储卷种类 五.在容器中使用存储卷 1.只声明容器路径 [root@localhost docker]# docker run ...
- 5.Docker存储卷
一.概述 1.Docker底层存储机制 Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层. 如果运行中的容器修改了现有的一个已经存在的文件,那 ...
- Docker系列03—Docker 存储卷
一.存储卷介绍 1.1 背景 Docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加而成,启动容器时,docker会加载只读镜像层并在镜像栈顶部加一个读写层: 如果运行的容器修改了 ...
- 你必须知道的Docker数据卷(Volume)
本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章. 一.将Docker数据挂载到容器 在Docker中,要想实现数据的持久化(所谓 ...
随机推荐
- Synchronized 和 Lock 锁在JVM中的实现原理以及代码解析
一.深入JVM锁机制:synchronized synrhronized关键字简洁.清晰.语义明确,因此即使有了Lock接口,使用的还是非常广泛.其应用层的语义是可以把任何一个非null对象作为&qu ...
- Appium+java 获取元素状态
元素的属性我们经常会用到,当定位到某个元素后,有时会需要用到这个元素的text值.className.resource-id.checked等. 一般标准的属性我们都可以通过get_attribut ...
- Spark操作HBase报:org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException异常解决方案
一.异常信息 19/03/21 15:01:52 WARN scheduler.TaskSetManager: Lost task 4.0 in stage 21.0 (TID 14640, hnte ...
- asp.net core 发布到 docker 容器时文件体积过大及服务端口的配置疑问
在 asp.net core 发布时,本人先后产生了3个疑问. 1.发布的程序为什么不能在docker容器中运行 当时在window开发环境中发布后,dotnet xxx.dll可以正常运行:但放入d ...
- 【转】JSF中的三大核心组件 UI标签的详细介绍和使用举例
JSF提供了大量的UI标签来简化创建视图.这些UI标签类似于ASP.NET中的服务器组件.使用这些标签,可以通过其value,binding,action,actionListener等属性直接绑定到 ...
- a标签的使用
a标签可以用来跳转页面请求路径,也可以用来绑定事件. 在绑定事件的时候,我需要控制a标签,不让他进行跳转. 这时候我要做的就是限制他,不让他跳转. 只需要在href属性中加入javascript:vo ...
- spring MVC,controller中获得resuqest和response的方式
package com.devjav.spring; import java.util.List; import java.util.Locale; import javax.servlet.http ...
- 洗礼灵魂,修炼python(72)--爬虫篇—爬虫框架:Scrapy
题外话: 前面学了那么多,相信你已经对python很了解了,对爬虫也很有见解了,然后本来的计划是这样的:(请忽略编号和日期,这个是不定数,我在更博会随时改的) 上面截图的是我的草稿 然后当我开始写博文 ...
- mysql 数据库安装
一.Mysql的安装 1. 安装mysql-server服务端 版本5.7.19-0ubuntu0.16.04.1 目前可以下载的版本: 5.5 5.6 5.7 8.0 测试版 输入:(我这里不需要客 ...
- TP中的图片水印
$img_dir = ROOT_PATH . 'public/upload/card/' . $data['jt_id']; //创建合成图片存放位置 //自动创建文件夹 if (!file_exis ...