Docker Volume 類型比較

發布於 2026-07-08 00:00 2676 字 14 min read

丁丁 avatar

丁丁

隨意寫寫,筆記記錄,以免忘記,後悔莫及

Docker #Linux Docker Volume 類型比較 1. Named Volumes (命名卷) Named Volumes 是由 Docker 管理的持久化儲存方案,資料儲存在 Docker 的管理目錄中(Linux 通常在 )。這是最推薦的資料持久化方式。 ✅ 由 Docker 完全管理,不需要指定主機路徑 ✅ 可以在多個容器間共享 ✅ 支援 volume...

#Docker #Linux

Docker Volume 類型比較

1. Named Volumes (命名卷)

說明

Named Volumes 是由 Docker 管理的持久化儲存方案,資料儲存在 Docker 的管理目錄中(Linux 通常在 /var/lib/docker/volumes/)。這是最推薦的資料持久化方式。

特點

  • ✅ 由 Docker 完全管理,不需要指定主機路徑
  • ✅ 可以在多個容器間共享
  • ✅ 支援 volume drivers,可擴展至遠端儲存
  • ✅ 容易備份和遷移
  • ✅ 在 Windows 和 Mac 上效能較好

Docker Compose 設定

services:
  db:
    image: postgres:15
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example

volumes:
  postgres_data:
    driver: local
    # 可選:指定 driver options
    driver_opts:
      type: none
      device: /path/on/host
      o: bind

Docker 命令

# 建立基本 volume
docker volume create my_volume

# 建立 volume 並指定 driver
docker volume create --driver local my_volume

# 建立 volume 並設定 driver_opts (對應 docker-compose 的 driver_opts)
docker volume create \
  --driver local \
  --opt type=none \
  --opt device=/path/on/host \
  --opt o=bind \
  postgres_data

# 使用短選項 -o (等同於 --opt)
docker volume create \
  --driver local \
  -o type=none \
  -o device=/absolute/path/on/host \
  -o o=bind \
  my_volume

# NFS volume 範例
docker volume create \
  --driver local \
  -o type=nfs \
  -o o=addr=192.168.1.100,rw \
  -o device=:/path/to/nfs/share \
  nfs_volume

# 使用 volume 啟動容器
docker run -d \
  --name my_container \
  -v my_volume:/app/data \
  nginx:latest

# 查看所有 volumes
docker volume ls

# 查看 volume 詳細資訊(包含 driver_opts)
docker volume inspect my_volume

# 刪除 volume
docker volume rm my_volume

# 清理未使用的 volumes
docker volume prune

Volume SubPath (掛載子目錄)

Docker 支援使用 volume-subpath 參數來掛載 volume 內的特定子目錄,而不是整個 volume。這在多容器共享同一 volume 時特別有用。

重要限制

  • 子目錄必須預先存在於 volume 中,否則掛載會失敗
  • 只能使用 --mount 語法,不支援 -v 簡短語法
  • Docker Compose 目前官方文件未明確說明支援此功能

Docker 命令語法

--mount src=<volume-name>,dst=<container-path>,volume-subpath=<subdir>

完整範例

# 1. 建立 volume
docker volume create logs

# 2. 初始化子目錄結構(必須先建立)
docker run --rm \
  --mount src=logs,dst=/logs \
  alpine mkdir -p /logs/app1 /logs/app2

# 3. App1 只掛載 logs volume 的 app1 子目錄
docker run -d \
  --name app1 \
  --mount src=logs,dst=/var/log/app,volume-subpath=app1 \
  myapp1:latest

# 4. App2 只掛載 logs volume 的 app2 子目錄
docker run -d \
  --name app2 \
  --mount src=logs,dst=/var/log/app,volume-subpath=app2 \
  myapp2:latest

# 5. 查看整個 volume 的內容(用於管理)
docker run --rm \
  --mount src=logs,dst=/logs \
  alpine ls -lR /logs

實用範例

# 建立共享資料 volume
docker volume create shared_data

# 初始化多個應用的子目錄
docker run --rm \
  --mount src=shared_data,dst=/data \
  alpine sh -c "
    mkdir -p /data/uploads/user1 /data/uploads/user2 &&
    mkdir -p /data/cache/app1 /data/cache/app2 &&
    chown -R 1000:1000 /data
  "

# 上傳服務 - 使用 uploads/user1 子目錄
docker run -d \
  --name upload_user1 \
  --mount src=shared_data,dst=/app/uploads,volume-subpath=uploads/user1 \
  upload_service:latest

# 快取服務 - 使用 cache/app1 子目錄
docker run -d \
  --name cache_app1 \
  --mount src=shared_data,dst=/app/cache,volume-subpath=cache/app1 \
  cache_service:latest

Docker Compose (非官方支援,但可變通)

Docker Compose 目前沒有直接的 volume-subpath 語法,但可以使用以下變通方式:

# 方法 1: 使用 driver_opts 將 volume 綁定到主機子目錄
services:
  app1:
    image: myapp:latest
    volumes:
      - app1_logs:/var/log/app

  app2:
    image: myapp:latest
    volumes:
      - app2_logs:/var/log/app

volumes:
  app1_logs:
    driver: local
    driver_opts:
      type: none
      device: /host/shared/logs/app1
      o: bind

  app2_logs:
    driver: local
    driver_opts:
      type: none
      device: /host/shared/logs/app2
      o: bind

# 方法 2: 使用 init 容器 + 環境變數
services:
  init:
    image: alpine
    volumes:
      - shared_data:/data
    command: mkdir -p /data/app1 /data/app2
    restart: "no"

  app1:
    image: myapp:latest
    depends_on:
      - init
    volumes:
      - shared_data:/data
    working_dir: /data/app1
    environment:
      DATA_PATH: /data/app1

  app2:
    image: myapp:latest
    depends_on:
      - init
    volumes:
      - shared_data:/data
    working_dir: /data/app2
    environment:
      DATA_PATH: /data/app2

volumes:
  shared_data:

使用場景

  • 多容器共享單一 volume 時隔離資料
  • 為每個容器維護獨立的日誌目錄
  • 精細控制資料存取範圍
  • 節省 volume 數量(一個 volume 多個用途)

使用場景

  • 資料庫資料持久化(PostgreSQL, MySQL, MongoDB)
  • 應用程式上傳的檔案儲存
  • 需要在多個容器間共享的資料
  • 生產環境的資料儲存

2. Bind Mounts (綁定掛載)

說明

Bind Mounts 將主機上的特定檔案或目錄直接掛載到容器中。提供了最直接的檔案系統存取,但依賴主機的檔案系統結構。

特點

  • ✅ 可以直接存取和編輯主機檔案
  • ✅ 適合開發環境的即時程式碼更新
  • ✅ 可以掛載單一檔案或整個目錄
  • ⚠️ 依賴主機的目錄結構
  • ⚠️ 在 Windows/Mac 上效能可能較差
  • ⚠️ 安全性較低(容器可以修改主機檔案)

Docker Compose 設定

services:
  web:
    image: node:18
    working_dir: /app
    volumes:
      # 長語法(推薦)
      - type: bind
        source: ./src
        target: /app
        read_only: false

      # 短語法
      - ./config:/app/config:ro  # :ro 表示唯讀
      - ./logs:/app/logs
    command: npm run dev
    ports:
      - "3000:3000"

  nginx:
    image: nginx:latest
    volumes:
      # 掛載設定檔
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      # 掛載靜態檔案
      - ./public:/usr/share/nginx/html:ro
    ports:
      - "80:80"

Docker 命令

# 使用絕對路徑掛載
docker run -d \
  --name dev_container \
  -v /absolute/path/on/host:/app \
  -v $(pwd)/config:/app/config:ro \
  node:18

# 使用相對路徑(需要完整路徑)
docker run -d \
  --name web \
  -v "$(pwd)":/app \
  -w /app \
  nginx:latest

# 掛載單一檔案
docker run -d \
  --name app \
  -v $(pwd)/.env:/app/.env:ro \
  myapp:latest

# 使用 --mount 語法(更明確,推薦)
docker run -d \
  --name app \
  --mount type=bind,source=$(pwd)/src,target=/app,readonly=false \
  node:18

使用場景

  • 開發環境的即時程式碼更新
  • 掛載設定檔到容器
  • 需要在主機上直接查看/編輯容器檔案
  • CI/CD 建置過程中的檔案共享

3. Anonymous Volumes (匿名卷)

說明

Anonymous Volumes 是沒有指定名稱的 volume,由 Docker 自動產生隨機名稱。當容器被刪除時,通常也會一起被刪除(除非使用特定選項)。

特點

  • ✅ 自動管理,無需手動建立
  • ✅ 適合臨時資料儲存
  • ⚠️ 難以追蹤和管理
  • ⚠️ 容器刪除後可能遺留孤立 volumes
  • ⚠️ 無法在容器間共享(每次都會建立新的)

Docker Compose 設定

services:
  app:
    image: node:18
    volumes:
      # 匿名 volume(不指定主機路徑或 volume 名稱)
      - /app/node_modules
      - /app/cache
    working_dir: /app
    command: npm start

  db:
    image: postgres:15
    volumes:
      # 結合 bind mount 和匿名 volume
      - ./app:/app                    # bind mount
      - /app/node_modules             # 匿名 volume,避免覆蓋
    environment:
      POSTGRES_PASSWORD: example

Docker 命令

# 建立匿名 volume
docker run -d \
  --name app \
  -v /app/data \
  nginx:latest

# 容器刪除時自動清理匿名 volume
docker run --rm \
  -v /tmp/cache \
  alpine:latest

# 查看容器的匿名 volumes
docker inspect app

# 範例:避免 node_modules 被覆蓋
docker run -d \
  --name node_app \
  -v $(pwd):/app \
  -v /app/node_modules \
  node:18

使用場景

  • 保護容器內特定目錄不被 bind mount 覆蓋(如 node_modules)
  • 臨時快取資料
  • 不需要持久化的資料
  • 開發環境的臨時檔案

4. tmpfs Mounts (臨時檔案系統掛載)

說明

tmpfs Mounts 將資料儲存在主機的記憶體中,不會寫入磁碟。當容器停止時,資料就會消失。只在 Linux 上可用。

特點

  • ✅ 極快的讀寫速度(記憶體存取)
  • ✅ 敏感資料不會寫入磁碟
  • ✅ 容器停止後自動清理
  • ⚠️ 資料不持久化
  • ⚠️ 佔用主機記憶體
  • ⚠️ 只支援 Linux

Docker Compose 設定

services:
  web:
    image: nginx:latest
    tmpfs:
      - /tmp
      - /run
    # 或使用長語法
    volumes:
      - type: tmpfs
        target: /app/cache
        tmpfs:
          size: 100M  # 限制大小為 100MB
          mode: 1777  # 設定權限

  app:
    image: myapp:latest
    volumes:
      - type: tmpfs
        target: /app/temp
        tmpfs:
          size: 50M
      - data:/app/data  # 結合 named volume

volumes:
  data:

Docker 命令

# 基本使用
docker run -d \
  --name app \
  --tmpfs /tmp \
  nginx:latest

# 使用 --mount 指定選項
docker run -d \
  --name app \
  --mount type=tmpfs,target=/app/cache,tmpfs-size=100M,tmpfs-mode=1770 \
  myapp:latest

# 多個 tmpfs mounts
docker run -d \
  --name app \
  --tmpfs /tmp:rw,size=50M,mode=1777 \
  --tmpfs /run:rw,size=10M \
  nginx:latest

# 查看掛載資訊
docker inspect app | grep -A 10 Mounts

使用場景

  • 敏感資料處理(密碼、金鑰等)
  • 高速快取需求
  • 臨時檔案處理
  • Session 儲存
  • 編譯過程的臨時檔案

Volume 類型比較表

特性Named VolumeBind MountAnonymous Volumetmpfs Mount
持久化✅ 是✅ 是✅ 是❌ 否
Docker 管理✅ 是❌ 否✅ 是❌ 否
主機路徑控制❌ 否✅ 是❌ 否❌ 否
容器間共享✅ 容易✅ 可以❌ 困難❌ 不可
效能(Linux)🟢 好🟢 好🟢 好🟢 極佳
效能(Win/Mac)🟢 好🟡 較差🟢 好N/A
備份容易度🟢 容易🟡 中等🔴 困難N/A
安全性🟢 高🟡 中等🟢 高🟢 高
使用複雜度🟢 簡單🟡 中等🟢 簡單🟢 簡單
生產環境✅ 推薦⚠️ 謹慎❌ 不推薦✅ 特定場景

實用技巧與最佳實踐

1. Volume 備份與還原

# 備份 named volume
docker run --rm \
  -v my_volume:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/backup.tar.gz -C /source .

# 還原 volume
docker run --rm \
  -v my_volume:/target \
  -v $(pwd):/backup \
  alpine tar xzf /backup/backup.tar.gz -C /target

2. 複製 Volume 資料

# 從一個 volume 複製到另一個
docker run --rm \
  -v old_volume:/from:ro \
  -v new_volume:/to \
  alpine sh -c "cd /from && cp -av . /to"

3. 組合使用範例

services:
  app:
    image: node:18
    volumes:
      # Bind mount: 開發時即時更新程式碼
      - ./src:/app/src

      # Named volume: 持久化上傳檔案
      - uploads:/app/uploads

      # Anonymous volume: 保護 node_modules
      - /app/node_modules

      # tmpfs: 高速快取
    tmpfs:
      - /app/cache:size=100M

  db:
    image: postgres:15
    volumes:
      # Named volume: 資料庫資料持久化
      - db_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example

volumes:
  uploads:
  db_data:

4. 清理未使用的 Volumes

# 清理所有未使用的 volumes
docker volume prune -f

# 清理特定 volume
docker volume rm volume_name

# 查看 volume 使用情況
docker system df -v

5. 使用 Volume SubPath 實現多租戶資料隔離

# 實際場景:多個微服務共享一個資料 volume,但各自有獨立空間

# 建立共享 volume
docker volume create microservices_data

# 初始化子目錄結構
docker run --rm \
  --mount src=microservices_data,dst=/data \
  alpine sh -c "
    mkdir -p /data/{auth,user,order}/{uploads,cache,logs} &&
    mkdir -p /data/shared/{config,templates} &&
    chown -R 1000:1000 /data
  "

# 認證服務 - 只能存取 auth 子目錄
docker run -d \
  --name auth_service \
  --mount src=microservices_data,dst=/app/data,volume-subpath=auth \
  --mount src=microservices_data,dst=/app/shared,volume-subpath=shared,readonly \
  auth:latest

# 使用者服務 - 只能存取 user 子目錄
docker run -d \
  --name user_service \
  --mount src=microservices_data,dst=/app/data,volume-subpath=user \
  --mount src=microservices_data,dst=/app/shared,volume-subpath=shared,readonly \
  user:latest

# 訂單服務 - 只能存取 order 子目錄
docker run -d \
  --name order_service \
  --mount src=microservices_data,dst=/app/data,volume-subpath=order \
  --mount src=microservices_data,dst=/app/shared,volume-subpath=shared,readonly \
  order:latest

# 管理容器 - 可以存取完整 volume(用於維護)
docker run --rm -it \
  --mount src=microservices_data,dst=/data \
  alpine sh

# 備份特定服務的資料
docker run --rm \
  --mount src=microservices_data,dst=/data,volume-subpath=auth \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/auth-$(date +%Y%m%d).tar.gz -C /data .

選擇建議

使用 Named Volumes 當

  • 生產環境的資料持久化
  • 需要簡單的備份和遷移
  • 資料需要在容器間共享
  • 使用 Windows 或 Mac 進行開發

使用 Bind Mounts 當

  • 開發環境需要即時程式碼更新
  • 需要精確控制檔案位置
  • 設定檔需要頻繁修改
  • 與主機工具整合(如 IDE)

使用 Anonymous Volumes 當

  • 保護特定目錄不被覆蓋
  • 臨時資料儲存
  • 不需要跨容器共享

使用 tmpfs Mounts 當

  • 處理敏感資料
  • 需要極高的 I/O 效能
  • 臨時快取或 session 儲存
  • 資料不需要持久化

參考資源

© 2010 - 2026 丁丁 @ThanatosDi
Powered by theme astro-koharu · Inspired by Shoka