五、Docker 核心技術:容器數據持久化之數據卷

Docker 容器本身是無狀態且生命周期短暫的。當一個容器被刪除時,它在可寫層產生的所有數據都會隨之消失。這對于需要持久化存儲數據的應用 (如數據庫、日志系統、用戶上傳內容) 來說是不可接受的。為了解決這個問題,Docker 提供了多種數據持久化方案,其中最重要、最推薦的就是數據卷

一、什么是容器數據卷

數據卷宿主機文件系統中一個特殊的目錄,它由 Docker 管理 (/var/lib/docker/volumes/ 目錄下),并可以直接映射一個或多個容器的指定目錄下。

數據卷的核心優勢:

數據持久化:數據卷的生命周期獨立于任何容器。即使所有使用該數據卷的容器都被刪除,數據卷及其中的數據依然存在
數據共享多個容器可以同時掛載同一個數據卷,從而實現容器間的數據共享和同步
高性能:數據卷繞過了容器的聯合文件系統 (UnionFS),直接讀寫宿主機的文件系統,具有接近原生的I/O性能。
易于管理:Docker 提供了專門的命令 (docker volume ...) 來創建、查看、刪除數據卷,便于備份、遷移和恢復

二、數據卷的使用

創建或運行容器時,我們主要使用 -v--mount 標志來掛載數據卷-v 語法更簡潔--mount 語法更明確推薦在生產環境和復雜場景下使用 --mount

1. 匿名掛載

如果你在 -v 標志中只指定容器內的路徑,Docker 會自動創建一個匿名的數據卷,并將其掛載到該路徑。

語法:

-v /path/in/container

代碼案例:

docker run -d -P --name nginx-anon -v /usr/share/nginx/html nginx
  • 這個命令會創建一個新的、名字是隨機哈希值的數據卷,并掛載到容器的 /usr/share/nginx/html 目錄。
  • 我們可以通過 docker inspect 查看這個匿名數據卷具體信息
docker inspect nginx-anon

在這里插入圖片描述

在輸出的 "Mounts" 部分,你會看到類似這樣的信息:

"Mounts": [{"Type": "volume","Name": "a1b2c3d4...", // 隨機生成的長哈希值"Source": "/var/lib/docker/volumes/a1b2c3d4.../_data","Destination": "/usr/share/nginx/html",...}
]

在這里插入圖片描述

  • 缺點:匿名掛載的數據卷名稱不直觀,難以管理和復用

2.具名掛載

這是最推薦的數據卷使用方式。你可以為數據卷指定一個有意義的名稱,方便后續的引用、共享和管理

語法:

-v 方式: volume-name:/path/in/container
--mount 方式: type=volume,source=volume-name,target=/path/in/container

代碼案例:

步驟一:創建具名數據卷 (可選,Docker會在掛載時自動創建)

docker volume create my-nginx-data

步驟二:使用具名數據卷運行容器

  • 使用 -v 標志:
docker run -d -P --name nginx-named-v -v my-nginx-data:/usr/share/nginx/html nginx
  • 使用 --mount 標志 (推薦):
docker run -d -P --name nginx-named-mount --mount type=volume,source=my-nginx-data,target=/usr/share/nginx/html nginx
  • 在這兩個例子中,名為 my-nginx-data數據卷掛載到了容器的 /usr/share/nginx/html 目錄。
  • 現在,你可以刪除并重建 nginx-named-vnginx-named-mount 容器,但只要重新掛載 my-nginx-data 數據卷,網站的數據 (如 index.html) 就會保持不變

數據卷管理命令:

# 列出所有數據卷
docker volume ls# 查看某個數據卷的詳細信息
docker volume inspect my-nginx-data# 刪除一個數據卷 (前提是沒有容器正在使用它)
docker volume rm my-nginx-data# 刪除所有不再被任何容器使用的懸空數據卷 (dangling volumes)
docker volume prune

在這里插入圖片描述
在這里插入圖片描述

3. 數據卷 vs 綁定掛載

除了由 Docker 管理的數據卷,Docker 還支持另一種強大的掛載方式——綁定掛載。它允許我們將宿主機上任意的一個文件或目錄直接映射到容器中。

綁定掛載語法 (使用 -v):

-v /path/on/host:/path/in/container

與數據卷的核心區別及選擇:

特性數據卷綁定掛載
管理方由 Docker 管理,位于 Docker 的專用存儲區域 (/var/lib/docker/volumes/)。由用戶管理,可以是宿主機文件系統中的任意路徑
可移植性。數據卷的定義與宿主機的目錄結構無關,便于在不同環境中遷移。。依賴于宿主機上特定的目錄結構,不易遷移。
性能在 Linux 上通常性能更高,因為它為數據I/O進行了優化。性能也很好,但可能受宿主機文件系統權限等因素影響。
權限Docker 自動處理權限。可能存在宿主機與容器內用戶權限不匹配的問題。
適用場景推薦用于生產環境和所有需要持久化應用數據的場景,如數據庫文件、應用日志等。適用于開發環境,如將源代碼目錄掛載到容器中進行實時代碼調試;或共享宿主機配置文件到容器。

代碼示例:直觀感受數據卷與綁定掛載的行為差異

這個示例將清晰地展示數據卷獨立于容器生命周期的特性,以及綁定掛載下宿主機與容器實時同步

場景一:使用數據卷的持久性演示

  1. 運行一個容器,使用具名數據卷并寫入數據:
docker run -d --name vol-test-container -v my-persistent-data:/data ubuntu sleep infinity
docker exec vol-test-container sh -c "echo 'This data is in a volume' > /data/message.txt"

在這里插入圖片描述

  • 此時,名為 my-persistent-data 的數據卷中已經包含了 message.txt 文件。
  1. 在容器內刪除文件,驗證宿主機數據卷不受影響:(為模擬容器內誤操作)
docker exec vol-test-container rm /data/message.txt

驗證容器內文件已刪除

docker exec vol-test-container ls /data

在這里插入圖片描述

(此時應無輸出)

關鍵點:此時 my-persistent-data 這個數據卷本身在宿主機上仍然包含 message.txt 文件。容器的刪除操作僅僅是在容器的可寫層記錄了“該文件已刪除”的標記并未真正刪除數據卷中的源文件。

  1. 刪除容器,然后創建一個新容器掛載同一個數據卷:
docker stop vol-test-container
docker rm vol-test-container# 創建一個全新的容器,掛載之前的數據卷
docker run --name vol-test-checker -it -v my-persistent-data:/data ubuntu
  1. 在新容器中查看數據:
    當你進入 vol-test-checker 容器的交互式終端后,查看 /data 目錄:
# 在 vol-test-checker 容器的shell中執行
ls /data
# 輸出應為:message.txtcat /data/message.txt
# 輸出應為:This data is in a volume

結論:這個實驗有力地證明了,數據卷中的數據是獨立且持久的。即使容器內的文件被看似“刪除”,或者整個容器刪除,數據卷中的原始數據安然無恙,可以被新的容器重新掛載和使用。

場景二:使用綁定掛載的實時同步演示

  1. 在宿主機上創建一個目錄和文件:
mkdir -p ./host-data
echo "Initial data from host" > ./host-data/sync.txt
  1. 運行一個容器,將宿主機目錄綁定掛載到容器中:
docker run -d --name bind-test-container -v $(pwd)/host-data:/data ubuntu tail -f /dev/null
  • tail -f /dev/null 是一個讓容器保持運行的技巧。
  • 現在,宿主機的 ./host-data 目錄與容器的 /data 目錄實時同步

在這里插入圖片描述
3. 驗證容器內可以看到宿主機文件:

docker exec bind-test-container cat /data/sync.txt
# 輸出應為:Initial data from host

在這里插入圖片描述
4. 宿主機上修改文件內容:

echo "Host updated the file" >> ./host-data/sync.txt
  1. 容器內立即查看變化:
docker exec bind-test-container cat /data/sync.txt
# 輸出現在應包含兩行:
# Initial data from host
# Host updated the file

在這里插入圖片描述

  1. 容器內刪除文件:
docker exec bind-test-container rm /data/sync.txt
  1. 宿主機上驗證文件是否也被刪除:
ls ./host-data/
# (此時應無輸出,文件已被刪除)

在這里插入圖片描述

結論:綁定掛載建立了宿主機和容器之間文件系統的直接鏈接。任何一方對掛載目錄中內容的修改或刪除,都會立即、真實地反映在另一方。這種實時同步的特性使其非常適合開發時共享源代碼

4. 綜合案例:使用具名數據卷持久化 MySQL 數據

這個案例將演示如何創建一個 MySQL 容器,并將其數據目錄 /var/lib/mysql 持久化到一個具名數據卷中,從而實現數據庫數據的安全存儲

步驟一:創建具名數據卷
為了清晰管理,我們先創建一個名為 mysql-data 的數據卷。

docker volume create mysql-data

步驟二:運行 MySQL 容器并掛載數據卷
我們將運行一個 MySQL 8.0 容器,并設置 root 密碼

docker run -d \
--name my-mysql \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
--mount type=volume,source=mysql-data,target=/var/lib/mysql \
mysql:8.0
  • -d: 后臺運行容器。
  • --name my-mysql: 為容器命名。
  • -p 3306:3306: 將宿主機的 3306 端口映射到容器的 3306 端口。
  • -e MYSQL_ROOT_PASSWORD=...: 通過環境變量設置 MySQL 的 root 用戶密碼。
  • --mount ...: 核心部分。將我們創建的 mysql-data 數據卷掛載到容器內部存放數據庫文件標準路徑 /var/lib/mysql

步驟三:驗證數據持久化

  1. 進入容器并創建數據
    使用 docker exec 進入正在運行的 MySQL 容器,并登錄到數據庫。
docker exec -it my-mysql mysql -uroot -pmysecretpassword

在 MySQL 命令行中,創建一個新的數據庫和表,并插入一些數據

CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50));
INSERT INTO users VALUES (1, 'Alice'), (2, 'Bob');
EXIT;

在這里插入圖片描述
主機也能正常連接上
在這里插入圖片描述

  1. 刪除容器
    現在,我們模擬一次容器故障或升級刪除這個 MySQL 容器。
docker stop my-mysql
docker rm my-mysql

此時,容器已經不存在了。

  1. 重新創建容器,掛載同一個數據卷
    我們再次運行一個 MySQL 容器,使用相同的命令,確保它掛載的還是 mysql-data 這個數據卷。
docker run -d \
--name my-mysql-new \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=mysecretpassword \
--mount type=volume,source=mysql-data,target=/var/lib/mysql \
mysql:5.7
  1. 驗證數據是否恢復
    等待新容器 my-mysql-new 完全啟動后,再次進入這個新容器。
docker exec -it my-mysql-new mysql -uroot -pmysecretpassword

在 MySQL 命令行中,檢查我們之前創建的數據庫和數據是否存在。

USE testdb;
SELECT * FROM users;

你會看到輸出

+----+-------+
| id | name  |
+----+-------+
|  1 | Alice |
|  2 | Bob   |
+----+-------+

證明了,即使容器被刪除存儲在數據卷中的數據被完美地保留了下來,并在新容器得以恢復

總結: 容器數據卷是實現Docker數據持久化首選方案。通過使用具名數據卷,我們可以安全地存儲應用數據解耦數據與容器的生命周期,并輕松實現數據的共享、備份和恢復,為在生產環境運行有狀態應用提供了堅實的基礎


練習題

題目一:創建與查看數據卷
寫出一條命令,創建一個名為 app-config 的具名數據卷,然后寫出另一條命令來查看這個數據卷的詳細信息。

題目二:匿名掛載
寫出一條命令,以后臺模式運行一個 ubuntu 容器,并為容器內的 /data 目錄進行匿名掛載。

題目三:具名掛載 (使用 -v)
寫出一條命令,以后臺模式運行一個名為 my-redisredis 容器,并使用 -v 標志將一個名為 redis-data 的具名數據卷掛載到容器的 /data 目錄。

題目四:具名掛載 (使用 --mount)
使用 --mount 標志重寫上一題的命令,實現完全相同的效果。

題目五:綁定掛載
寫出一條命令,運行一個臨時的、交互式的 alpine 容器,并將宿主機當前目錄下的 app 子目錄 (假設為 ./app) 綁定掛載到容器的 /app 目錄。容器啟動后執行 ls /app 命令。

題目六:數據共享

  1. 首先,運行一個名為 writer-containerbusybox 容器,將一個名為 shared-volume 的數據卷掛載到 /shared。容器啟動后,向 /shared/message.txt 文件寫入 “Hello from writer”。
  2. 然后,運行另一個名為 reader-containerbusybox 容器,同樣掛載 shared-volume 數據卷到 /shared,并讀取 /shared/message.txt 文件的內容。
    (請分別寫出這兩個 docker run 命令)

題目七:數據卷清理
寫出一條命令,可以一次性刪除所有當前未被任何容器使用的Docker數據卷。

題目八:數據卷數據備份
假設 mysql-data 數據卷中包含了重要的數據庫文件,你希望對其進行備份。請描述一種簡單的、利用另一個臨時容器來備份該數據卷中所有文件到宿主機 /backup 目錄的思路或命令。

答案與解析

答案一:
創建數據卷:

docker volume create app-config

查看詳細信息:

docker volume inspect app-config

解析: docker volume create 用于創建具名數據卷,docker volume inspect 用于查看其元數據,包括在宿主機上的實際存儲路徑。

答案二:

docker run -d --name ubuntu-anon -v /data ubuntu

解析: -v 標志后只跟了容器內的路徑 /data,這會觸發Docker創建一個匿名數據卷并掛載到此路徑。

答案三:

docker run -d --name my-redis -v redis-data:/data redis

解析: -v 標志使用 [volume_name]:[container_path] 的格式來進行具名掛載。如果 redis-data 數據卷不存在,Docker會自動創建它。

答案四:

docker run -d --name my-redis --mount type=volume,source=redis-data,target=/data redis

解析: --mount 標志使用更明確的鍵值對語法。type=volume 指定類型,source 指定數據卷名稱,target 指定容器內路徑。

答案五:

docker run --rm -it --mount type=bind,source=$(pwd)/app,target=/app alpine ls /app

解析: --mount type=bind 指定了綁定掛載。source=$(pwd)/app 表示宿主機當前工作目錄下的 app 目錄。--rm 使容器退出后自動刪除,-it 提供交互式終端。容器啟動后直接執行 ls /app 命令。

答案六:

  1. 運行 writer-container
docker run --name writer-container -v shared-volume:/shared busybox sh -c "echo 'Hello from writer' > /shared/message.txt"
  1. 運行 reader-container
docker run --name reader-container -v shared-volume:/shared busybox cat /shared/message.txt

解析: 兩個容器都掛載了同一個具名數據卷 shared-volume。第一個容器向卷中寫入文件,第二個容器可以立即讀取到這個文件,實現了數據共享。

答案七:

docker volume prune

解析: docker volume prune 是一個方便的命令,用于清理不再被任何(包括已停止的)容器引用的數據卷,可以釋放磁盤空間。

答案八:

docker run --rm \
--mount type=volume,source=mysql-data,target=/dbdata,readonly \
--mount type=bind,source=/backup,target=/backup_host \
ubuntu \
tar czvf /backup_host/mysql-backup-$(date +%Y%m%d).tar.gz -C /dbdata .

在這里插入圖片描述

日期:2025年9月5日
專欄:Docker教程

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/921372.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/921372.shtml
英文地址,請注明出處:http://en.pswp.cn/news/921372.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

前端視覺交互設計全解析:從懸停高亮到多維交互體系(含代碼 + 圖表)

在前端用戶體驗領域,視覺交互是連接用戶與產品的 “隱形橋梁”—— 它通過可視化信號傳遞操作意圖、反饋系統狀態,直接決定用戶對產品的感知。很多開發者對視覺交互的認知停留在 “鼠標懸停高亮”,但實際上,視覺交互是一個覆蓋 “…

從零打造商業級LLMOps平臺:開源項目LMForge詳解,助力多模型AI Agent開發!

最近,我發現了一個超級實用的開源項目——LMForge-End-to-End-LLMOps-Platform-for-Multi-Model-Agents(以下簡稱LMForge)。這個項目是一個端到端的LLMOps(Large Language Model Operations)平臺,專為多模型…

【C++練習】06.輸出100以內的所有素數

目錄輸出100以內的所有素數方法1:基礎判斷法方法2:埃拉托斯特尼篩法(效率更高)方法3:優化版篩法(只考慮奇數)方法4:使用STL算法方法5:遞歸實現總結: 輸出100以…

在開發中使用git rebase的場景

rebase介紹 一、背景 遠程倉庫有oh4w-dev和oh4k-dev兩個分支,oh4k-dev是基于oh4w-dev開發到80%的代碼新拉的分支;此后兩條分支同步開發,當oh4k-dev開發完成,oh4w-dev還在開發階段,oh4k-dev需要拉取到oh4w-dev自分出o…

TDengine 時序函數 NOW() 用戶手冊

TDengine NOW() 函數用戶使用手冊 目錄 功能概述函數語法返回值說明技術特性使用場景及示例時間運算操作注意事項常見問題 功能概述 NOW() 函數是 TDengine 中的時間函數,用于獲取客戶端當前系統時間。該函數在時序數據庫中特別有用,可以用于數據插入…

JavaWeb ——事務管理

文章目錄事務管理事務回顧Spring事務管理事務進階事務屬性 - 回滾 rollbackFor事務屬性 - 傳播行為 propagationSpring框架第一大核心: IOC控制反轉, 其第二大核心就是 AOP 面向切面編程 事務管理 事務回顧 Spring事務管理 # spring 事務管理日志 logging:level:org…

【跨國數倉遷移最佳實踐8】MaxCompute Streaming Insert: 大數據數據流寫業務遷移的實踐與突破

本系列文章將圍繞東南亞頭部科技集團的真實遷移歷程展開,逐步拆解 BigQuery 遷移至 MaxCompute 過程中的關鍵挑戰與技術創新。本篇為第八篇,MaxCompute Streaming Insert: 大數據數據流寫業務遷移的實踐與突破。注:客戶背景為東南…

2025-09-05 CSS4——浮動與定位

文章目錄1 顯示(Display)1.1 visibility:hidden1.2 display:none2 塊和內聯元素2.1 塊元素2.2 內聯元素2.3 改變元素的顯示方式3 浮動(Float)3.1 float 屬性3.2 clear 屬性4 定位(Position)4.1 五種定位模式…

43這周打卡——生成手勢圖像 (可控制生成)

目錄 前言 1.導入數據及數據可視化 2.構建模型 3.訓練模型 4.模型分析并生成指定圖像 總結 前言 🍨 本文為🔗365天深度學習訓練營中的學習記錄博客🍖 原作者:K同學啊 1.導入數據及數據可視化 from torchvision import data…

TDengine 時間函數 TIMEDIFF() 用戶手冊

TDengine TIMEDIFF() 函數詳細使用手冊 目錄 功能概述函數語法參數說明返回值說明版本變更說明技術特性使用場景及示例時間單位處理數據類型兼容性注意事項常見問題最佳實踐 功能概述 TIMEDIFF() 函數用于計算兩個時間戳的差值,返回 expr1 - expr2 的結果。結果…

【2025ICCV-持續學習方向】一種用于提示持續學習(Prompt-based Continual Learning, PCL)的新方法

1. 背景與問題 (Background & Problem):?? ?持續學習 (CL):?? 目標是在不遺忘舊任務知識的情況下,讓模型持續學習一系列新任務。主要挑戰是災難性遺忘。 ?基于提示的持續學習 (PCL):?? 利用預訓練視覺Transformer (ViT),凍結其權重,通過微調稱為“提示”(prompt…

2025 年 08 月 GitHub 十大熱門項目排行榜

歡迎來到 2025 年 8 月 GitHub 熱門開源項目排行榜!本月榜單集中展示了來自智能體平臺、AI 編程助手、多模態角色系統、本地化部署工具到可視化白板與企業協同平臺的多元創新。從構建 AI 助手中樞的 Archon,到終端 AI 編碼拍檔 Crush,再到虛擬…

LeetCode每日一題,2025-9-4

多數元素 投票法 讓你找到序列中出現超過二分之一的元素,一定要記住這個規則。 記錄兩個值val和cnt,剛開始val為任意數,cnt0。 如果cnt是0,就把當前val num。接下來判斷,ifnum val,則cnt ,e…

第7章 安全配置

7.1 安全概述 Jenkins安全威脅 常見安全風險: 訪問控制風險: - 未授權訪問Jenkins實例 - 權限提升攻擊 - 橫向移動攻擊 - 敏感信息泄露代碼執行風險: - 惡意腳本注入 - 構建腳本篡改 - 插件漏洞利用 - 遠程代碼執行數據安全風險: …

騰訊混元世界模型Voyager開源:單圖生成3D世界的“核彈級”突破,游戲、VR、自動駕駛迎來新變量

當AI繪畫、視頻生成技術逐漸從“新鮮感”走向“實用化”,3D內容生成卻始終卡在“效率低、成本高、門檻高”的瓶頸里。傳統3D建模需要專業軟件、大量人工調整,甚至依賴昂貴的硬件設備,讓中小團隊和個人創作者望而卻步。 但騰訊AI實驗室最近開…

數據庫(基礎操作)

SQL 結構化的查詢語句 我們現在需要寫SQL語句 --- 這個玩意兒就是數據庫的操作語句我們的數據庫就類似于一個excl表格它有n列,每一列為一個大類,數據以行存在,一行代表一個條目數據如:我現在想建立一個數據庫保存學生的信息你需要…

linux ubi文件系統

1,UBI(Unsorted Block Images)是 Linux 內核中為原始 Flash 設備提供的一種抽象層,位于 MTD(Memory Technology Device)和文件系統(如 UBIFS)之間。它負責壞塊管理、磨損均衡、邏輯卷…

深度厚金板PCB與厚銅PCB的區別

厚金板PCB和厚銅PCB在電子制造領域都有重要應用,它們有著不同的特點和適用場景。下面為你詳細介紹二者的區別。厚金PCB是什么厚金PCB是在印制電路板表面鍍上較厚金層的電路板。這層厚金能提升電路板的導電性、抗氧化性和耐磨性。在一些對信號傳輸要求極高、使用環境…

一階低通濾波器應用示例(演示)

1. 代碼 這段代碼實現了一個一階低通濾波器(也稱為指數加權移動平均濾波器)。它適用于需要平滑數據、減少噪聲的場合。以下是一些常見的應用場景: 傳感器數據平滑:在嵌入式系統或物聯網設備中,傳感器(如溫度…

RT-Thread源碼分析字節實現socket源碼

無論是客戶端還是服務器程序,發送的底層都是發送AT指令:1)發送命令到串口;2)阻塞等待返回結果接收的底層都是1)阻塞等待;2)被喚醒后拷貝處理數據兩者均由后臺任務喚醒,后…