docker存储卷

news2024/11/26 4:31:51

docker存储卷

COW机制

Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。

如果运行中的容器修改了现有的一个已经存在的 文件,那么该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本依然存在,只是已经被读写层中该文件的副本所隐藏,这就是“写时复制(COW)”机制。

在这里插入图片描述

对于这种方式来说,我们去访问一个文件,修改和删除等一类的操作,其效率会非常的低,因为隔着很多层镜像。

而要想绕过这种限制,我们可以通过使用存储卷的机制来实现。

什么是存储卷

存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。

在这里插入图片描述

在宿主机上的这个与容器形成绑定关系的目录被称作存储卷。

使用存储卷的好处

如果容器中跑的进程的所有有效数据都保存在存储卷中,从而脱离容器自身文件系统之后,带来的好处是当容器关闭甚至被删除时,只要不删除与此容器绑定的在宿主机上的这个存储目录,我们就不用担心数据丢失了。因此就可以实现数据持久,脱离容器的生命周期而持久。

我们通过这种方式管理容器,容器就可以脱离主机的限制,可以在任意一台部署了docker的主机上跑容器,而其数据则可以置于一个共享存储文件系统上,比如nfs。

Docker的存储卷默认情况下是使用其所在的宿主机上的本地文件系统目录的,也就是说宿主机上有一块属于自己的硬盘,这个硬盘并没有共享给其他的Docker主机,而在这台主机上启动的容器所使用的存储卷是关联到此宿主机硬盘上的某个目录之上。

这就意味着容器在这台主机上停止运行或者被删除了再重建,只要关联到硬盘上的这个目录下,那么其数据还存在。但如果在另一台主机上启动一个新容器,那么数据就没了。而如果在创建容器的时候我们手动的将容器的数据挂载到一台nfs服务器上,那么这个问题就不再是问题了。

为什么要用存储卷

关闭并重启容器,其数据不受影响,但删除Docker容器,则其更改将会全部丢失。

因此Docker存在的问题有:

  • 存储于联合挂载文件系统中,不易于宿主机访问
  • 容器间数据共享不便
  • 删除容器其数据会丢失

而要解决这些问题,解决方案就是使用存储卷。

存储卷管理方式

存储卷(Data Volume)于容器初始化时被自动创建,由base image提供的卷中的数据会于此期间完成复制。

Volume的初衷是独立于容器的生命周期实现数据持久化,因此删除容器之时既不会删除卷,也不会对未被引用的卷做垃圾回收操作。

存储卷为Docker提供了独立于容器的数据管理机制,我们可以把镜像想象成静态文件,例如“程序”,把卷类比为动态内容,例如“数据”。所以镜像可以重用,而卷则可以共享。

卷实现了“程序(镜像)”和“数据(卷)”的分离,以及“程序(镜像)”和“制作镜像的主机”的分离,用户制作镜像时无须再考虑镜像运行的容器所在的主机的环境。

在这里插入图片描述

存储卷的分类

Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上的位置有所不同:

  • Bind mount volume(不是手动的删除,即使删除容器,也存在)
    • a volume that points to a user-specified location on the host file system
  • Docker-managed volume (删除容器,不存在)
    • the Docker daemon creates managed volumes in a portion of the host’s file system that’s owned bye Docker

在这里插入图片描述

示例: 删除容器数据还在

# 在容器中
[root@localhost ~]# docker run -it --rm httpd /bin/bash
root@3279d1258e83:/usr/local/apache2# ls
bin  build  cgi-bin  conf  error  htdocs  icons  include  logs	modules
root@3279d1258e83:/usr/local/apache2# exit
exit

# 在真机中
[root@localhost ~]# mkdir /webroot
[root@localhost ~]# 

[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@localhost ~]# docker run -d --rm -v /webroot:/usr/local/apache2/htdocs httpd 
f76e2c2e9c91319beb0c085198287955e3ae932c2b0a4c239acafcbd84e126d6
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND              CREATED         STATUS         PORTS     NAMES
f76e2c2e9c91   httpd     "httpd-foreground"   8 seconds ago   Up 6 seconds   80/tcp    youthful_visvesvaraya
[root@localhost ~]# 

# 进入容器
[root@localhost ~]# docker exec -it f76e2c2e9c91 /bin/bash
root@f76e2c2e9c91:/usr/local/apache2# cd htdocs/
root@f76e2c2e9c91:/usr/local/apache2/htdocs# ls //什么都没有
root@f76e2c2e9c91:/usr/local/apache2/htdocs# 


# 在真机创建一个网站页面
[root@localhost ~]# cd /webroot/
[root@localhost webroot]# echo "hello world" > index.html
[root@localhost webroot]# ls
index.html
[root@localhost webroot]# 

# 再次查看容器中
root@f76e2c2e9c91:/usr/local/apache2/htdocs# ls
index.html //有了在真机中创建的网站网页

# 停止容器,测试是否数据还在
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND              CREATED         STATUS         PORTS     NAMES
f76e2c2e9c91   httpd     "httpd-foreground"   6 minutes ago   Up 6 minutes   80/tcp    youthful_visvesvaraya
[root@localhost ~]# docker stop f76e2c2e9c91 
f76e2c2e9c91
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@localhost ~]

# 查看
[root@localhost webroot]# ls
index.html //数据依然还在
[root@localhost webroot]# 

# 访问一下
[root@localhost ~]# docker run -d --rm -v /webroot:/usr/local/apache2/htdocs httpd 
fa0eeebc1c586be93eaa0fd47825c7eb7111bed3eb5b6760716b3d8485a0506b
[root@localhost ~]# 
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND              CREATED         STATUS         PORTS     NAMES
fa0eeebc1c58   httpd     "httpd-foreground"   6 seconds ago   Up 4 seconds   80/tcp    charming_heisenberg
[root@localhost ~]# curl 172.17.0.2
hello world //依然可以访问
[root@localhost ~]# 
 
 # 进入容器查看是否数据还在
 [root@localhost ~]# docker exec -it fa0eeebc1c58 /bin/bash
root@fa0eeebc1c58:/usr/local/apache2# ls htdocs/
index.html
root@fa0eeebc1c58:/usr/local/apache2#

容器数据管理

用户在使用Docker的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据的共享,这必然涉及容器的数据管理操作。

容器中管理数据主要有两种方式:

  • 数据卷(Data Volumes)
  • 数据卷容器(Data Volumes Containers)

容器Volume使用语法:
Docker-managed volume

语法格式:docker run -it --name CONTAINER_NAME -v VOLUMEDIR IMAGE_NAME

[root@localhost ~]# docker run -it --rm -v /data busybox //data与真机的某个目录绑定,没有指定,没有固定的位置
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # cd data/
/data # ls
/data # touch abc
/data # 



# 查看
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
28ef103fb798   busybox   "sh"      5 minutes ago   Up 5 minutes             amazing_beaver
[root@localhost ~]# 

[root@localhost ~]# docker inspect 28ef103fb798
  "Mounts": [
            {
                "Type": "volume",
                "Name": "63e268c29a5ffe57d1c2cee5f47d9ef956fdeb3e408039754caa953f94bc462f",
                "Source": "/var/lib/docker/volumes/63e268c29a5ffe57d1c2cee5f47d9ef956fdeb3e408039754caa953f94bc462f/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
[root@localhost ~]# cd /var/lib/docker/volumes/63e268c29a5ffe57d1c2cee5f47d9ef956fdeb3e408039754caa953f94bc462f/_data //这个位置时随机的
[root@localhost _data]# ls
[root@localhost _data]# ls
abc  //因为做了映射
[root@localhost _data]# 

Bind mount volume

语法格式:docker run -it --name CONTAINER_NAME -v HOSTDIR:VOLUMEDIR IMAGE_NAME

[root@localhost ~]# docker run -it --rm -v /host/data:/data busybox 
/ # 
# 开另外一个终端查看
[root@localhost ~]# ls /
........
boot  etc  host (host被创建) .....
[root@localhost /]# ls host/
data
[root@localhost /]

# 在容器中data目录中也是空的并创建一个文件
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # cd data/
/data # ls
/data # touch abc
/data # 

# 在真机中查看
[root@localhost /]# ls host/data/
abc
[root@localhost /]# 

# 退出容器并查看数据是否还在
[root@localhost /]# ls host/data/
abc

在容器中使用数据卷

在容器内创建一个数据卷

下面使用nginx镜像创建一个web容器,并创建一个数据卷挂载到容器的/webapp目录下:

[root@localhost ~]# docker run -d -P --name web -v /webapp nginx

这里的-P是允许外部访问容器需要暴露的端口

挂载一个主机目录作为数据卷

[root@localhost ~]# docker run -d -P --name web1 -v /var/www/html:/webapp nginx

上面的命令加载主机的/var/www/html目录到容器的/webapp目录:
这个功能在进行测试的时候非常方便,比如用户可以放置一些程序或数据到本地目录中,然后在容器内运行和使用。另外,本地目录的路径必须是绝对路径,如果目录不存在,Docker会自动创建。

Docker挂载数据卷的默认权限是读写(rw),用户也可以通过(ro)指定为只读:

[root@localhost ~]# docker run -d -P --name web2 -v /var/www/html:/webapp:ro nginx
[root@localhost ~]# docker run -it --rm -v /host/data:/data:ro busybox 
/ # cd /data/
/data # ls 
abc
/data # echo "hello world" >> abc
sh: can't create abc: Read-only file system //会报错不可以创建,因为只读模式
/data # 

# 但是可以在真机中写,然后容器中也会一样
[root@localhost data]# echo "hello world" >> abc
[root@localhost data]#

# 在容器中查看
/data # cat abc 
hello world
/data # 

加了:ro以后,容器内挂载的数据卷的数据就无法修改了。

挂载一个本地主机文件作为数据卷
-v选项也可以从主机挂载单个文件到容器中作为数据卷:

[root@localhost ~]# docker run -it --rm -v ~/.bash_history:/.bash_history centos /bin/bash

如果直接挂载一个文件到容器,使用文件编辑工具,包括vi或者sed去修改文件内容的时候,可能会造成inode的改变,这样将会导致错误。所以推荐的方式是直接挂载文件所在的目录。

数据卷容器

如果用户需要在容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。数据卷容器其实就是一个普通的容器,专门用它提供数据卷供其他容器挂载使用,方法如下:

首先,创建一个数据卷容器dbdata,并在其中创建一个数据卷挂载到/dbdata:

[root@localhost ~]# docker run -it -d --name dbdata -v /dbdata centos

示例:

[root@localhost ~]# docker run -it --rm --name dbdata -v /dbdata busybox
/ # ls
bin     dev     home    root    tmp     var
dbdata  etc     proc    sys     usr
/ # cd dbdata/
/dbdata # ls
/dbdata # 

然后可以在其他容器中使用–volumes-from来挂载dbdata容器中的数据卷,例如创建db1和db2两个容器,并从dbdata容器挂载数据卷:

[root@localhost ~]# docker run -d --name db1 --volumes-from dbdata centos
[root@localhost ~]# docker run -d --name db2 --volumes-from dbdata centos
示例:

# 第一个容器
[root@localhost data]#  docker run -it --rm --volumes-from dbdata busybox
/ # ls 
bin     dev     home    root    tmp     var
dbdata  etc     proc    sys     usr
/ # cd dbdata/
/dbdata # 
# 第二个容器
root@localhost ~]# docker run -it --rm --volumes-from dbdata busybox
/ # ls 
bin     dev     home    root    tmp     var
dbdata  etc     proc    sys     usr
/ # cd dbdata/  这是两个dbdata 里面都是空的

# 在第一台容器中添加内容

/dbdata # echo 'hello world' > abc
/dbdata # ls
abc
/dbdata # cat abc 
hello world
/dbdata # 

# 查看第二台容器
/ # cd dbdata/
/dbdata # ls
abc
/dbdata # cat abc 
hello world
/dbdata # 
即使删除dbdata容器,数据依然存在

此时,容器db1和db2都挂载同一个数据卷到相同的/dbdata目录。三个容器任何一方在该目录下的写入,其他容器都可以看到。
例如,在db1容器中创建一个test文件:

[root@localhost ~]# docker exec -it db1 /bin/bash
[root@75b50c43ce20 /]# ls
bin  dbdata  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@75b50c43ce20 /]# cd dbdata/
[root@75b50c43ce20 dbdata]# touch test
[root@75b50c43ce20 dbdata]# ls

在db2容器中查看:

[root@localhost ~]# docker exec -it db2 /bin/bash
[root@c0b4bb5ff5b9 /]# ls dbdata/
test

可以多次使用–volumes-from参数来从多个容器挂载多个数据卷。还可以从其他已挂载了容器卷的容器来挂载数据卷:

[root@localhost ~]# docker run -d --name db3 --volumes-from db1 centos

使用–volumes-from参数所挂载数据卷的容器自身并不需要保持在运行状态。

如果删除了挂载的容器(包括dbdata、db1和db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式使用docker rm -v命令来指定同时删除关联的容器。

利用数据卷容器迁移数据

可以利用数据卷容器对其中的数据卷进行备份、恢复,以实现数据的迁移。

备份
使用下面的命令来备份dbdata数据卷容器内的数据卷:

[root@localhost ~]# docker run --name worker --volumes-from dbdata -v $(pwd):/backup centos tar cvf /backup/backup.tar /dbdata

这个命令稍微有点复杂,具体分析下。
首先利用centos镜像创建了一个容器worker。使用–volumes-from dbdata参数来让worker容器挂载dbdata容器的数据卷(即dbdata数据卷);使用-v $(pwd):/backup参数来挂载本地的当前目录到worker容器的/backup目录。
worker容器启动后,使用了tar cvf /backup/backup.tar /dbdata命令来将/dbdata下内容备份为容器内的/backup/backup.tar,即宿主主机当前目录下的backup.tar。

恢复
如果要恢复数据到一个容器,可以按照下面的操作。首先创建一个带有数据卷的容器dbdata2:

[root@localhost ~]# docker run -it --name dbdata2 -v /dbdata centos /bin/bash

然后创建另一个新的容器,挂载dbdata2容器,并使用untar解压备份文件到所挂载的容器卷中即可:

[root@localhost ~]# docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/bac

批量删除容器

[root@localhost ~]# docker ps -a

[root@localhost ~]# docker rm -f $(docker ps -aq)

批量删除镜像

[root@localhost ~]# docker ps -aq
[root@localhost ~]# docker images -q
beae173ccac6
605c77e624dd
dabbfbe0c57b
dabbfbe0c57b
[root@localhost ~]# docker rmi -f $(docker images -q)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1179233.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5米DEM高程数据分析和对比

数字高程模型(DEM)是应用最广泛的地理信息数据之一,是进行三维空间处理和地形分析的数据基础。每个行业数据精度要求不一样,很多行业使用公开免费的90米和30米分辨率DEM就够了。而城市规划、交通线路规划、地质灾害防控、城区地籍…

【QT】 Qt自定义ui控件

在使用Qt的ui设计时,Qt为我们提供了标准的窗口控件,但是在很多复杂工程中,标准窗口控件并不能满足所有的需求,这时就需要我们自定义控件。我们自定义的类既可以作为独立的窗口显示,又可以作为一个控件显示。 我们要实现…

Spring相关

SpringBoot自动装配 阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台 Spring相关 阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台 常用设计模式 双亲委派 Java虚拟机定义了三个主要的类加载器: 1、启动类加载器 2、扩展类加载器 …

python教程:打印心型图案 九九乘法表 三角形 金字塔 圣诞树 倒三角形 菱形

# 打印九九乘法口诀表 for i in range(1, 10): # 乘法表的行、起始值从1开始for j in range(1, i 1): # 表示每一行的表达式、从1开始、到j1print({}*{}{}.format(j, i, i * j), end ) # 输出语句{}占位、输出表达式print( )# 打印金字塔(正三角形) …

web3 dapp React项目引入 antd 对 balance 用户token信息组件进行样式改造

好 上文 web3 React dapp中编写balance组件从redux取出并展示用户资产 我们简单处理了用户资产的展示 那么 我们继续 先启动 ganache 环境 终端输入 ganache -d然后 打开我们的项目 将合约发布到区块链上 truffle migrate --reset然后 我们启动项目 确认一切正常 还原到上文…

wangeditor富文本编辑器的使用(vue)

官网 官方demo 参考 安装 yarn add wangeditor/editor yarn add wangeditor/editor-for-vue 封装的富文本组件 <template><div style"border: 1px solid #ccc"><Toolbarstyle"border-bottom: 1px solid #ccc":editor"editorRef"…

P02项目(学习)

★ P02项目 项目描述&#xff1a;安全操作项目旨在提高医疗设备的安全性&#xff0c;特别是在医生离开操作屏幕时&#xff0c;以减少非授权人员的误操作风险。为实现这一目标&#xff0c;我们采用多层次的保护措施&#xff0c;包括人脸识别、姿势检测以及二维码识别等技术。这些…

工程压缩与解压缩

很多工程师在完成一个电气工程后&#xff0c;会遇到一些问题&#xff0c;例如&#xff1a;在SOLIDWORKSElectrical 中如何把做好的工程发送给别的工程师&#xff0c;或者更换了电脑如何把旧电脑的工程转移到新电脑 上&#xff1b;有时候&#xff0c;工程师也有可能会遇到解压工…

Redis概述和安装

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349; 本篇详细阐述了Redis概述和安装&#xff0c;如有出入…

经典OJ题:找环节点——代码解析

题目&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测…

【每日一题】统计范围内的元音字符串数

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;遍历 其他语言python3 写在最后 Tag 【遍历】【数组】【2023-11-07】 题目来源 2586. 统计范围内的元音字符串数 题目解读 统计范围内的元音字符串数。 解题思路 方法一&#xff1a;遍历 遍历下标在 [left, right]…

用循环结构程序自动化计算——计数循环

用循环结构程序自动化计算——计数循环 低阶目标&#xff1a; 利用for循环结构来完成已知次数的自动化处理&#xff0c;掌握计数循环结构应用方法 高阶目标&#xff1a; 学会利用for循环解决生活中的实际问题 用循环结构程序自动化计算——计数循环 用循环结构程序自动化计算…

Leetcode48旋转图像

思路&#xff1a;找规律 方法一、一般辅助数组解法 行列转换&#xff0c;第一行变到第三列&#xff0c;第二行变到第二列&#xff0c;第三行变到第一列 matrix[row][col] matrix[col][n-row-1] 然后复制回原数组 class Solution {public void rotate(int[][] matrix) {in…

第十二章 Python正则表达式

系列文章目录 第一章 Python 基础知识 第二章 python 字符串处理 第三章 python 数据类型 第四章 python 运算符与流程控制 第五章 python 文件操作 第六章 python 函数 第七章 python 常用内建函数 第八章 python 类(面向对象编程) 第九章 python 异常处理 第十章 python 自定…

独立键盘接口设计(Keil+Proteus)

前言 软件的操作参考这篇博客。 LED数码管的静态显示与动态显示&#xff08;KeilProteus&#xff09;-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/134101256?spm1001.2014.3001.5501实验&#xff1a;用4个独立按键控制8个LED指示灯。 按下k1键&#x…

VB.NET—DataGridView控件教程详解

目录 前言: 过程: 第一步: 第二步: 第三步: 第四步: 第五步&#xff1a; 番外篇: 总结: 前言: DataGridView是.NET FormK中的一个Windows窗体控件&#xff0c;它提供了一个可视化的表格控件&#xff0c;允许用户以表格形式显示和编辑数据。它通常用于显示和编辑数据库…

50基于matlab的传统滤波、Butterworth滤波、FIR、移动平均滤波、中值滤波、现代滤波、维纳滤波、自适应滤波、小波变换

基于matlab的传统滤波、Butterworth滤波、FIR、移动平均滤波、中值滤波、现代滤波、维纳滤波、自适应滤波、小波变换&#xff0c;七种滤波方法&#xff0c;可替换自己的数据进行滤波&#xff0c;程序已调通&#xff0c;可直接运行。 50matlabButterworth滤波 (xiaohongshu.com)…

AI创作系统ChatGPT商业运营系统源码+支持GPT4/支持ai绘画

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

关于 HTML 的一切:初学者指南

HTML 代表超文本标记语言&#xff0c;是用于创建网页和 Web 应用程序的标准语言。 本指南将全面介绍 HTML&#xff0c;涵盖从基本语法和语义到更高级功能的所有内容。 我的目标是用简单的术语解释 HTML&#xff0c;以便即使没有编码经验的人也能学习如何使用 HTML 构建网页。…

Ps:色彩范围

Ps菜单&#xff1a;选择/色彩范围 Select/Color Range 色彩范围 Color Range是一个功能强大选择命令&#xff0c;不仅可以基于颜色进行选择&#xff0c;而且可以基于影调进行选择。不仅可以用来检测人脸选择肤色&#xff0c;也可用来选择超出印刷色域范围的区域。 在图层蒙版的…