Docker 数据卷的使用与数据持久化(一)

引言

在容器化技术的广阔天地里,Docker 无疑是一颗璀璨的明星,它以轻量级、高效部署等特性,彻底改变了应用程序的交付和运行方式。在 Docker 的众多核心特性中,数据卷(Volume)犹如基石一般,支撑着容器化应用的数据持久化和数据共享需求,成为了 Docker 生态中不可或缺的关键部分。

容器的本质是一种轻量级、可移植的运行环境,它的设计理念是将应用及其依赖打包在一起,实现快速部署和隔离运行。然而,这种临时性的运行环境也带来了一个问题:当容器停止或被删除时,容器内产生的数据将会丢失。这对于许多需要长期保存数据的应用场景,如数据库、文件存储系统等,是无法接受的。数据卷的出现,正是为了解决这一难题。它提供了一种将容器内的数据存储在宿主机或其他持久化存储介质上的机制,使得数据能够独立于容器的生命周期而存在,从而实现了数据的持久化。

除此之外,数据卷还为容器之间的数据共享提供了便利。在微服务架构盛行的今天,一个应用往往由多个相互协作的容器组成,这些容器之间需要共享数据来实现业务逻辑。通过数据卷,不同的容器可以轻松地访问和修改同一组数据,极大地提高了容器之间的协作效率。

无论是从数据持久化的角度,还是从容器间数据共享的需求出发,Docker 数据卷都扮演着举足轻重的角色。接下来,让我们深入探索 Docker 数据卷的世界,了解它的原理、使用方法以及在实际应用中的最佳实践。

Docker 数据卷基础概念

数据卷是什么

Docker 数据卷是一种特殊的目录,它绕过了容器的联合文件系统(Union File System),实现了容器与宿主机之间或多个容器之间的数据共享和持久化存储。简单来说,数据卷就像是一座桥梁,连接着容器内的应用程序和宿主机的文件系统,使得容器内产生的数据能够存储在宿主机上,或者让多个容器能够访问和修改同一份数据。

从技术原理上讲,数据卷的实现依赖于宿主机的文件系统挂载机制。当我们在创建容器时指定挂载一个数据卷,Docker 会在宿主机上创建一个对应的目录(对于命名卷)或使用一个自动生成的目录(对于匿名卷),并将其挂载到容器内指定的路径上。这样,容器内对该路径的读写操作实际上就是对宿主机上对应目录的操作。例如,在一个 Web 应用容器中,我们可以将存储用户上传文件的目录挂载为数据卷,这样即使容器被删除或重新创建,用户上传的文件也不会丢失,因为它们存储在宿主机的数据卷中。

命名卷与匿名卷

在 Docker 中,数据卷主要分为命名卷(Named Volumes)和匿名卷(Anonymous Volumes),它们在创建方式、生命周期和用途上各有特点。

  • 命名卷:命名卷是通过用户明确指定名称创建的数据卷。我们可以使用 docker volume create 命令来手动创建一个命名卷,例如 docker volume create my_data_volume,这将创建一个名为 my_data_volume 的数据卷。在启动容器时,通过 -v my_data_volume:/container/path 这样的语法将命名卷挂载到容器内的指定路径。命名卷的生命周期独立于容器,即使所有挂载它的容器都被删除,命名卷仍然会保留在宿主机上,直到我们手动使用 docker volume rm my_data_volume 命令将其删除。由于其可命名和持久化的特性,命名卷非常适合用于需要长期保存数据的场景,如数据库存储。例如,在运行 MySQL 容器时,可以将 MySQL 的数据目录挂载到一个命名卷上,这样在容器升级、重启或故障恢复时,数据库数据都能得到保留。
  • 匿名卷:匿名卷是在容器运行时自动创建的数据卷,我们在创建容器时只需要指定容器内的挂载路径,而无需指定宿主机上的对应路径,Docker 会自动为其分配一个宿主机上的目录。例如,docker run -d -v /app/data my_app_image 这条命令会创建一个匿名卷并挂载到容器内的 /app/data 路径。匿名卷的生命周期与容器紧密相关,当容器被删除时,如果没有使用特殊选项,匿名卷也会被自动删除。匿名卷常用于临时数据存储或不需要长期保存的数据场景,比如在构建容器镜像过程中,用于存储中间编译产物的目录可以挂载为匿名卷,在镜像构建完成后,这些临时数据就可以随着容器和匿名卷的删除而自动清理。

数据卷的优势

数据卷在 Docker 容器化应用中具有诸多显著优势,这些优势使得它成为实现数据持久化和容器间协作的关键技术。

  • 数据持久性:这是数据卷最核心的优势之一。容器的本质是轻量级、可快速创建和销毁的运行环境,默认情况下,容器内的数据存储在容器的可写层中,当容器停止或被删除时,这些数据也会随之丢失。而通过数据卷,将数据存储在宿主机或其他持久化存储介质上,数据的生命周期不再依赖于容器,从而确保了数据的持久性。无论是数据库中的业务数据,还是应用程序生成的日志文件,都可以通过数据卷进行持久化保存,为应用的稳定运行提供了可靠的数据基础。
  • 数据共享:数据卷为容器之间的数据共享提供了便捷的方式。在一个复杂的微服务架构中,可能存在多个相互协作的容器,例如一个 Web 应用容器需要与一个文件存储容器共享用户上传的文件,或者多个后端服务容器需要共享配置文件。通过将同一个数据卷挂载到多个容器上,这些容器就可以方便地访问和修改共享数据,实现了容器之间的高效协作,同时也避免了在容器之间通过网络传输数据带来的性能开销和复杂性。
  • 备份与恢复:数据卷使得数据的备份和恢复操作变得更加简单和高效。由于数据卷中的数据存储在宿主机上,我们可以直接对宿主机上的数据卷目录进行备份操作,例如使用常见的文件备份工具(如 tar、rsync 等)将数据卷目录打包并存储到其他存储介质中。在需要恢复数据时,只需将备份文件解压缩到相应的数据卷目录,然后重新启动使用该数据卷的容器,容器就可以恢复到备份时的数据状态。这对于灾难恢复和数据迁移等场景具有重要意义,能够大大缩短业务中断时间,提高系统的可用性。
  • 性能优化:相比于在容器内存储数据,使用数据卷可以提升数据读写性能。因为数据卷直接使用宿主机的文件系统进行读写操作,避免了容器联合文件系统的额外开销,减少了数据读写的层次和复杂性,从而能够获得更好的 I/O 性能。特别是对于那些对数据读写性能要求较高的应用场景,如数据库应用、大数据处理应用等,使用数据卷能够显著提升应用的整体性能表现。
  • 镜像轻量化:将应用程序的数据存储在数据卷中,而不是打包到镜像内部,可以有效地减小镜像的大小。这不仅能够加快镜像的构建速度,减少构建过程中的资源消耗,还能在镜像传输和部署时,降低网络带宽的占用,提高部署效率。同时,较小的镜像也更便于管理和维护,降低了镜像存储和分发的成本。

Docker 数据卷的使用方法

命令行创建与管理数据卷

在 Docker 中,通过命令行可以便捷地创建和管理数据卷,这为我们在容器化应用中实现数据持久化和共享提供了基础操作手段。

  • 创建数据卷:使用 docker volume create 命令可以创建一个命名数据卷。例如,要创建一个名为 my_database_volume 的数据卷,只需在命令行中输入 docker volume create my_database_volume。Docker 会在宿主机的默认数据卷存储路径(通常是 /var/lib/docker/volumes/)下创建一个对应的目录来存储该数据卷的数据。创建命名数据卷时,还可以指定一些驱动选项,以满足不同的存储需求。比如,对于需要高性能存储的数据库应用,可以使用支持高速读写的存储驱动,如 local 驱动的一些优化版本(在某些特定存储硬件上的定制驱动)。命令示例如下:docker volume create --driver local --opt type=ext4 --opt device=/dev/sda1 my_fast_database_volume,这里通过 --driver 指定了驱动类型为 local,并通过 --opt 选项设置了文件系统类型为 ext4,以及使用特定的存储设备 /dev/sda1。
  • 查看数据卷:docker volume ls 命令用于列出当前系统中所有的数据卷。执行该命令后,会得到一个数据卷列表,显示每个数据卷的名称和一些基本信息。如果想要查看某个具体数据卷的详细信息,如挂载点、驱动信息等,可以使用 docker volume inspect 命令,例如 docker volume inspect my_database_volume,它会以 JSON 格式返回该数据卷的详细配置和状态信息,包括其在宿主机上的实际存储路径、所属的驱动以及权限设置等。
  • 删除数据卷:当某个数据卷不再被使用时,可以使用 docker volume rm 命令将其删除。例如,要删除前面创建的 my_database_volume,执行 docker volume rm my_database_volume 即可。但需要注意的是,在删除数据卷之前,必须确保没有容器正在挂载该数据卷,否则删除操作会失败。为了避免误删重要数据卷,在执行删除操作前,最好先确认该数据卷是否仍被使用,可以通过 docker inspect 命令查看各个容器的挂载信息,或者使用一些工具(如 Portainer 等可视化管理工具)来直观地查看数据卷与容器的关联关系。此外,Docker 还提供了 docker volume prune 命令,用于一次性删除所有未被使用的数据卷,帮助清理系统中无用的数据卷,释放磁盘空间。不过在使用该命令时要格外小心,因为它会删除所有未被任何容器挂载的数据卷,可能会导致一些意外的数据丢失。

容器挂载数据卷

在启动容器时,挂载数据卷是实现数据持久化和共享的关键步骤,通过 -v 参数可以轻松完成这一操作。

  • 基本挂载语法:基本的挂载语法为 docker run -d --name [容器名称] -v [宿主机路径或数据卷名称]:[容器内路径] [镜像名称]。例如,我们要启动一个 MySQL 容器,并将一个名为 mysql_data 的数据卷挂载到容器内的 /var/lib/mysql 目录(这是 MySQL 默认的数据存储目录),命令如下:docker run -d --name mysql_container -v mysql_data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root mysql:latest。这里 -d 表示以守护进程模式在后台运行容器,--name 为容器指定名称,-v 后面的 mysql_data:/var/lib/mysql 表示将 mysql_data 数据卷挂载到容器内的 /var/lib/mysql 路径,-e 用于设置环境变量,这里设置了 MySQL 的 root 用户密码,最后指定了使用的 MySQL 镜像为 mysql:latest。这样,MySQL 容器在运行过程中产生的所有数据,包括数据库文件、日志等,都会存储在 mysql_data 数据卷中,即使容器被删除或重新创建,数据也不会丢失。
  • 读写权限设置:在挂载数据卷时,还可以设置读写权限。默认情况下,数据卷是以读写权限(rw)挂载到容器中的。如果希望将数据卷以只读权限(ro)挂载,只需在挂载参数中添加 :ro 即可。例如,docker run -d --name my_app -v /host/config:/app/config:ro my_app_image,这条命令将宿主机上的 /host/config 目录以只读权限挂载到容器内的 /app/config 目录,这样容器内的应用程序只能读取该目录下的配置文件,而无法对其进行修改,从而保证了配置文件的安全性和一致性。这种设置在一些需要保护配置文件不被容器内应用程序意外修改的场景中非常有用,比如在运行一些基于微服务架构的应用时,多个微服务容器可能共享相同的配置文件,通过只读挂载可以确保每个容器都使用相同的配置,并且不会因为某个容器的异常操作而破坏配置文件。
  • 挂载多个数据卷:一个容器可以挂载多个数据卷,以满足不同的数据存储和共享需求。例如,一个 Web 应用容器可能需要将存储用户上传文件的目录挂载为一个数据卷,同时将应用的日志目录也挂载为另一个数据卷。命令示例如下:docker run -d --name web_app -v uploads_volume:/var/www/uploads -v logs_volume:/var/log/web_app my_web_app_image。这里分别将 uploads_volume 数据卷挂载到容器内的 /var/www/uploads 目录,用于存储用户上传的文件;将 logs_volume 数据卷挂载到容器内的 /var/log/web_app 目录,用于存储应用的日志文件。通过这种方式,实现了不同类型数据的分别管理和持久化存储,同时也方便了对这些数据的单独备份、恢复和管理。在实际应用中,根据业务的复杂程度,一个容器可能需要挂载更多的数据卷,每个数据卷负责存储特定类型的数据,从而提高数据管理的灵活性和可维护性。

数据卷容器

数据卷容器是一种特殊的容器,它主要用于管理和共享数据卷,为多个容器之间的数据共享提供了一种高效的解决方案。

  • 概念与作用:数据卷容器本身并不运行实际的应用程序,它的主要作用是作为数据卷的载体,将数据卷集中管理起来。通过数据卷容器,可以方便地在多个容器之间共享相同的数据卷,实现数据的集中存储和管理。例如,在一个复杂的分布式系统中,有多个微服务容器需要共享一些配置文件、公共数据等,此时可以创建一个数据卷容器,并将这些共享数据存储在该容器挂载的数据卷中,然后让其他微服务容器通过挂载这个数据卷容器来访问共享数据。这样,当需要更新共享数据时,只需要在数据卷容器中进行操作,所有挂载该数据卷容器的其他容器都能立即获取到最新的数据,大大提高了数据管理的效率和一致性。
  • 创建与使用:创建数据卷容器的方法与创建普通容器类似,但需要特别指定挂载的数据卷。例如,要创建一个名为 data_volume_container 的数据卷容器,并挂载一个名为 shared_data_volume 的数据卷,命令如下:docker create -v shared_data_volume:/data --name data_volume_container busybox。这里使用 docker create 命令创建了一个容器,-v shared_data_volume:/data 表示将 shared_data_volume 数据卷挂载到容器内的 /data 目录,--name 指定了容器的名称为 data_volume_container,最后指定使用 busybox 镜像(这是一个小巧的 Linux 工具集镜像,适合用于这种不需要运行复杂应用的场景)。创建好数据卷容器后,其他容器可以通过 --volumes-from 参数来挂载这个数据卷容器的数据卷。例如,有两个应用容器 app_container_1 和 app_container_2 需要共享 shared_data_volume 数据卷中的数据,启动这两个容器的命令如下:
 

docker run -d --name app_container_1 --volumes-from data_volume_container my_app_image_1

docker run -d --name app_container_2 --volumes-from data_volume_container my_app_image_2

这样,app_container_1 和 app_container_2 都可以访问和修改 shared_data_volume 数据卷中的数据,实现了数据在多个容器之间的共享。而且,由于数据卷容器的存在,数据的管理和维护变得更加集中和方便。如果需要对共享数据进行备份或迁移,只需要操作数据卷容器挂载的数据卷即可,而不需要分别对每个应用容器进行处理。

  • 数据卷容器的优势:相比于直接在多个容器之间挂载相同的数据卷,使用数据卷容器具有以下优势。首先,它提供了更好的数据隔离和安全性。因为数据集中存储在数据卷容器挂载的数据卷中,其他容器只能通过挂载数据卷容器来访问数据,无法直接对数据卷进行操作,降低了数据被误操作或恶意篡改的风险。其次,数据卷容器使得数据管理更加集中和高效。通过数据卷容器,可以统一对共享数据进行更新、备份、恢复等操作,而不需要在每个使用该数据的容器中分别进行处理,大大减少了管理成本和出错的可能性。此外,数据卷容器还具有更好的可扩展性。当需要添加更多的容器来共享相同的数据时,只需要让新容器挂载已有的数据卷容器即可,无需重新配置和管理数据卷,方便了系统的扩展和维护。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rustdesk远程桌面自建服务器

首先,我这里用到的是阿里云服务器 centos7版本,win版客户端。 准备工作 centos7 服务器端文件: https://github.com/rustdesk/rustdesk-server/releases/download/1.1.11-1/rustdesk-server-linux-amd64.zip win版客户端安装包&#xff1…

PostgreSQL有undo表空间吗?

PostgreSQL有undo表空间吗 PostgreSQL 没有单独的 Undo 表空间,其事务回滚和多版本并发控制(MVCC)机制与 Oracle 等数据库有显著差异。 一 PostgreSQL 的 MVCC 实现 PostgreSQL 通过 多版本并发控制(MVCC) 管理事务…

Java项目《苍穹外卖》BUG修复记录

一、订单详情地址显示为null 原因:查看订单详情接口中,未设置收货地址信息,故地址返回为null。 解决方案: 1、OrderServiceImpl中创建一个私有方法专门获取订单收货地址 /*** 获取订单收获地址* param addressBookId* return*/…

NO.18十六届蓝桥杯备战|循环嵌套|乘法表|斐波那契|质数|水仙花数|(C++)

循环嵌套 循环嵌套的使⽤ while , do while , for ,这三种循环往往会嵌套在⼀起才能更好的解决问题,就是我们所说的:循环嵌套。这三种循环都可以任意嵌套使⽤ ⽐如: 写⼀个代码,打印⼀个乘法⼝…

【第6章:强化学习基础与深度强化学习—6.4 强化学习在游戏、自动驾驶等领域的应用案例】

你是否想过,为什么《王者荣耀》的AI总能预判你的走位?特斯拉的Autopilot如何实现复杂路况的决策?这背后都藏着一个改变人工智能格局的技术——强化学习。今天我们将深入这个让机器学会"思考"的黑科技,揭开它从基础理论到工业应用的全貌。 一、强化学习的"…

【Linux内核】进程管理(上)

一、进程简介 关于进程相关内容直接看我的操作系统专栏,在这里不再赘述。我们直接快进到Linux中的进程管理部分 二、Linux中的进程描述符 晋城市操作系统中调度的实体,因此需要对进程的信息、所持有的资源进行描述,这种抽象描述称之为进程…

类和对象(5)——抽象类和接口

目录 1. 抽象类 1.1 抽象类的概念 1.2 抽象类语法:abstract关键字 1.3 抽象类的特性 1.4 抽象类的作用 2. 接口 2.1 接口的概念 2.2 接口语法:interface关键字 2.3 接口的实现:implements关键字 2.4 接口的特性 2.5 实现多个接口 …

利用租用的GPU进行训练

对于大模型的微调以及推理,对显卡的要求较高,我们就可以通过租一台来进行训练,这里我租用的是:AutoDL算力云 | 弹性、好用、省钱。租GPU就上AutoDL 推荐博客:新手小白如何租用GPU云服务器跑深度学习_gpu租用-CSDN博客…

[操作系统] 基础IO:系统文件I/O

在 Linux 操作系统中,文件 I/O(输入/输出)是程序与文件系统交互的基础。理解文件 I/O 的工作原理对于编写高效、可靠的程序至关重要。本文将深入探讨系统文件 I/O 的机制。 一种传递标志位的方法 在 Linux 中,文件的打开操作通常…

Qt MainWindow

文章目录 0. 概述1. 菜单栏 QMenuBar1.1 例子1,使用图形化界面1.2 例子2,使用代码创建1.3 例子3,添加快捷键1.4 例子4,添加子菜单1.5 例子5,添加分割线和图标1.6 内存泄漏问题 2. 工具栏 QToolBar2.1 例子1&#xff0c…

阅读论文“用于车联网安全车载通信的机器学习技术“的学习笔记

前言 论文全称为Machine Learning Technologies for Secure Vehicular Communication in Internet of Vehicles: Recent Advancesc and Applications 智能交通系统(ITS)和计算系统的快速发展为智能交通安全提供了新的科学研究,并提供了舒适和…

[java] 集合-Collection、ArrayList、LinkedList源码篇

目录 Collection集合 集合类体系结构 常用方法 遍历方式 迭代器遍历 增强for lambda表达式 List集合 特有方法 五种遍历方式 细节点注意 List集合的实现类 List集合子类的特点 LinkedList集合的特有功能 源码分析 ArrayList源码分析 LinkedList源码分析 迭代…

DeepSeek自动化写作软件

DeepSeek写作软件的三大核心功能 对于内容创作者来说,写作不仅是表达思想的过程,更是一项需要投入大量时间和精力的任务。面对日益增长的内容需求,写作效率低下、内容质量不高等问题,常常让创作者感到焦虑。而 DeepSeek 写作软件…

前端里的this指向问题

目录 1.代码输出结果 2.代码输出结果 3.代码输出结果 4.代码输出结果 5.代码输出结果 6.代码输出结果 7.代码输出结果 8.代码输出结果 9.代码输出结果 10.代码输出结果 11.代码输出结果 12.代码输出结果 13.代码输出结果 14.代码输出结果 总结 1.代码输出结果 f…

苹果CMS新版站群管理更新_新增批量生成插件优势何在

引言 随着互联网的发展,站群管理成为了网站运营者提升流量和SEO效果的重要策略。苹果CMS新版站群管理系统通过引入批量生成插件,为用户提供了更高效、更智能的解决方案。本文将详细介绍这一更新的功能特点及其优势。 站群管理功能特点 多域名独立配置…

时序约束进阶八:时钟抖动Jitter与不确定性Uncertainty

目录 一、前言 二、时钟抖动 2.1 时钟抖动类型 2.2 set_input_jitter 2.3 set_system_jitter 2.4 set_clock_uncertainty 2.5 设计代码 2.6 约束解析 2.7 Input_jitter报告 2.8 System Jitter报告 2.9 Clock Uncertainty报告 2.9.1 Uncertainty的计算 2.9.2 Uncer…

小米 R3G 路由器(Pandavan)实现网络打印机功能

小米 R3G 路由器(Pandavan)实现网络打印机功能 一、前言 家中有多台 PC 设备需要打印服务,但苦于家中的 Epson L380 打印机没有网络打印功能,并且配置 Windows 共享打印机实在是过于繁琐且需要共享机保持唤醒状态过于费电。想到…

Leetcode Hot100 第30题 416.分割等和子集

class Solution { public:bool canPartition(vector<int>& nums) {int sum0;for(int num:nums){sumnum;}if(sum%21) return false;int bag_size sum/2;// return dfs(nums,nums.size()-1,bag_size);//递归做法vector<vector<bool>> dp(nums.size()1,vec…

技术晋升读书笔记—阿里管理三板斧(二)

一、引子 美团王兴问马云&#xff1a;“你最强的地方是什么&#xff1f;” 马云反问王兴&#xff1a;“你觉得呢&#xff1f;” 王兴回答&#xff1a;“战略和忽悠。” 马云哈哈大笑&#xff0c;笑完&#xff0c;他一本正经地说&#xff1a;“我最强的地方是管理。” &quo…

引入了 Disruptor 后,系统性能大幅提升!

Disruptor 是一个很受欢迎的内存消息队列&#xff0c;它源于 LMAX 对并发、性能和非阻塞算法的研究。今天一起来学习一下这个消息队列。 简介 对于主流的分布式消息队列来说&#xff0c;一般会包含 Producer、Broker、Consumer、注册中心等模块。比如 RocketMQ 架构如下&…