Skip to main content

Volumes

Image 裡的資料多半只能讀;要在 container 裡寫入、且刪掉 container 後還能保留,就靠 Volume。

為什麼需要 Volume?​

在 image 裡面我們所能抓到的值,通常只能 read;container 啟動後,對檔案系統可以 read / write,但 container 一刪除,寫進去的資料就會跟著消失。

若要讓資料跨 container 生命週期持久化,或讓本機檔案與容器內路徑同步,就使用 Volume(含 named volume 與 bind mount)。

Data 種類​

容器內常見的資料可分成三類,對應不同的讀寫與存放位置:

種類例子讀寫存在哪裡
Application(code + env)應用程式碼、預設設定多半 read-onlyImage
Temporary(cache, log, user input)cache、log、暫存輸入read-writeContainer(刪容器就沒了)
Persistent(database, config, media)DB 資料、設定檔、上傳媒體read-writeContainer + Volume

一句話:會刪容器也要留下的,就掛 Volume;只存在這次執行的,放 container 即可。

Volume 寫法兩種​

在 docker-compose.yml 的 volumes: 裡,常見兩種掛法:

寫法語法概念適合的 data 種類說明
Named volumevolume_name:/container/pathPersistent(DB、cache 持久層)由 Docker 管理;需在頂層 volumes: 宣告
Bind mount./host/path:/container/path 或 ${ENV}:/pathPersistent(媒體、設定)/把本機檔案注入 container直接對應主機路徑;可加 :ro 唯讀

:ro = read-only,適合「本機設定檔掛進 container,但不允許容器改回本機」。

實例:MediaCMS Compose 的 Volumes​

以下節錄一組實際服務(redis + web + celery_worker)的 volumes 用法,並對回上面的 data 種類。

services:
redis:
image: redis:alpine
restart: unless-stopped
volumes:
- redis_data:/data

web:
image: mediacms/mediacms:latest
platform: linux/amd64
restart: unless-stopped
depends_on:
- redis
env_file:
- .env
volumes:
# MediaCMS 實際寫入 media_files,不是 media
- ${LOCAL_MEDIA_PATH}:/home/mediacms.io/mediacms/media_files
- ${LOCAL_STATIC_PATH}:/home/mediacms.io/mediacms/static_collected
# entrypoint 會把此檔 copy 到 cms/local_settings.py
- ./local_settings.py:/home/mediacms.io/mediacms/deploy/docker/local_settings.py:ro
# API 強制登入(DRF 不受 GLOBAL_LOGIN_REQUIRED 保護)
- ./api_auth_middleware.py:/home/mediacms.io/mediacms/cms/api_auth_middleware.py:ro
- ./api_service_auth.py:/home/mediacms.io/mediacms/cms/api_service_auth.py:ro
ports:
- "80:80"

celery_worker:
image: mediacms/mediacms:latest
platform: linux/amd64
restart: unless-stopped
depends_on:
- redis
- web
env_file:
- .env
volumes:
# worker 轉檔必須與 web 共用同一 media_files
- ${LOCAL_MEDIA_PATH}:/home/mediacms.io/mediacms/media_files
- ./local_settings.py:/home/mediacms.io/mediacms/deploy/docker/local_settings.py:ro
- ./api_auth_middleware.py:/home/mediacms.io/mediacms/cms/api_auth_middleware.py:ro
- ./api_service_auth.py:/home/mediacms.io/mediacms/cms/api_service_auth.py:ro

volumes:
redis_data:

逐項對照​

掛載類型Data 種類為什麼這樣掛
redis_data:/dataNamed volumePersistentRedis 資料要在 down / 重建 container 後仍保留;由 Docker 管理,不必關心主機實際路徑
${LOCAL_MEDIA_PATH}:.../media_filesBind mountPersistent上傳/轉檔後的媒體檔;web 與 celery_worker 必須掛同一路徑,否則 worker 讀不到 web 寫入的檔
${LOCAL_STATIC_PATH}:.../static_collectedBind mountPersistent(或部署產物)收集後的靜態檔放本機,方便備份、換機或反向代理直接讀
./local_settings.py:...:roBind mount + roApplication / config用本機設定覆寫部署預設;:ro 避免 container 改到本機檔
./api_*.py:...:roBind mount + roApplication(自訂程式)把客製 middleware/auth 掛進 image 內路徑,等同注入程式碼,仍用唯讀較安全

設計重點​

  1. Named volume 給「服務自己的狀態」:如 redis_data,對應 Persistent。
  2. Bind mount 給「要跟本機/多服務共用」的檔:如 media_files,web 寫、worker 讀,必須同一掛載。
  3. 設定與自訂程式用 :ro:屬於 Application/config 注入,不該被 container 寫回本機。
  4. 沒掛 Volume 的暫存(例如 container 內 log、cache)仍屬 Temporary,刪容器就沒了——若要留,再另掛 volume。

總結​

  • Image:Application,偏 read-only。
  • Container alone:Temporary,read-write 但易丟。
  • Volume:Persistent,read-write 且可跨重建保留。
  • Compose 裡:named volume 管服務狀態;bind mount 管本機路徑與多服務共用;設定檔/客製 code 常加 :ro。