Volume 進階用法
今天開始,會說明 Docker 更多的細節。未來如果需要維運 container 或用到 container 調度系統(如 K8S),則接下來十天的內容,將有可能幫上一點忙。
首先第一天要介紹的是 Volume 的進階用法。說是進階用法,其實只是比一開始提到的同步程式操作複雜了點而已。
Volume 概念
原本同步程式的做法很單純,只是把本機的某個位置綁在 container 的某個路徑上,如:
docker run -d -it -v $PWD:/usr/local/apache2/htdocs -p 8080:80 httpd |
這樣會把 host 下指令的路徑綁在 container 的 /usr/local/apache2/htdocs
上。
上面的方法達成了 host 共享資料給 container,但有時候會是 container 之間需要共用資料。可以試著執行下面的指令來了解如何做到這件事:
# 建立 volume,並命名為 code |
這段指令很長,仔細說明如下:
- 先開一個空的目錄叫
code
然後掛載到 BusyBox 的/source
下,並產生程式碼。 - 注意這裡使用 BusyBox 都有加
--rm
參數,所以每次 container 都會移除,但code
裡面的資料不會消失 - Nginx container
my-web
把code
拿來掛載到,且可以正常使用 - Nginx container
my-web2
把my-web
的掛載設定拿來用,且可以正常使用
-v
參數掛載
這次掛載的參數使用方法如下:
-v [VOLUME_NAME]:[CONTAINER_PATH] |
VOLUME_NAME
若不存在,會建立一個同名 volume(背後執行 docker volume create --name VOLUME_NAME
);若存在,則會做掛載。
Volume 的名字有限定不能有斜線 /
:
$ docker volume create --name a/b |
所以有斜線,且是絕對路徑的話,就代表的是 bind mount,沒有斜線代表的是 volume。
-v
也可以不指定 VOLUME_NAME
如下:
-v [CONTAINER_PATH] |
Docker 會使用 docker volume create
建立 volume,名稱會是一個隨機亂數,並掛載到 CONTAINER_PATH
。
--volumes-from
參數
有時候會需要跟其他 container 共同相同的 volume 設定,比方像上例,同樣的 web 服務,都會有相同的設定。
--volumes-from
這時候就會非常好用,它後面要接的參數是 CONTAINER_ID
。它會把該 container 的 volume 設定原封不動的複製過去,包括 bind mount。
應用
可以想像,在 Docker 的世界裡,container 跟 volume 是兩個不同且獨立元件,然後可以使用 docker run 組裝起來。
以上面這個圖來說,兩個 Web container 共同使用 Code volume,而 DB container 使用 Data volume。因 volume 是獨立的元件,所以我們可以執行其他 container,把對應的 volume 拿來讀取做其他應用。
DB 備份
我不懂 MySQL,就當 MySQL 要停止才能備份好了。
# 啟動 MySQL |
這是個簡單的範例,裡面有兩個重點:
- 啟動 MySQL 的時候,其實已經內帶 volume 了,它的行為會是加上
-v /var/lib/mysql
參數 - BusyBox 會把
-v /var/lib/mysql
複製過來,因此 tar 指令後面要接/var/lib/mysql
路徑
MySQL 內帶 volume 是由 Dockerfile 指令設定的:
VOLUME /var/lib/mysql |
其他 DB 像 Redis 也有類似的設定:
VOLUME /data |
主要是因為這類需要 persistent 資料的服務,都會設定 VOLUME
讓其他 container 可以共用並做其他處理,如備份。
Nginx + PHP-FPM
除了 DB 會用到 volume 外,也遇過這個情境需要用到 volume 設定。主要是因為 Nginx 需要對應路徑要真的有 .php 檔案,它才會往 FPM 送出請求。Docker Compose 檔範例如下:
web: |
屬性設定
Container 共享檔案雖然很方便,但有時候會希望限制權限。比方說回頭看第一個範例,假設我們只希望 BusyBox 才能有寫入權限,Nginx 只有唯讀權限,則可以加上屬性參數如下:
# BusyBox 不變 |
屬性設定格式如下:
-v [VOLUME_NAME]:[CONTAINER_PATH]:[PROPERTIES] |
此外 Mac 的效能問題也可以調整屬性設定解決。
Volume driver
以上都是以 container 共用檔案的前提在說明如何運用 volume。事實上,volume 獨立元件設計,更好用的地方在於,它可以使用不同的 driver 來替換實體的儲存位置。比方說,直接透過 volume driver 掛載 SSH 上的某個目錄--sshfs。
這部分僅知道概念,但沒有經驗,有興趣可以參考官網說明。
指令補充說明
docker volume create
建立 volume
--name
指定 volume 名稱
docker run
-v|--volume
掛載 volume 到 container 裡面的某個目錄--volumes-from
新的 container 會共享舊的 container 的 volume 設定。
今日自我回顧
知道 volume 的設定方法,雖然在開發上沒有什麼影響,但在維運應用上就能有更多變化。
比方說,假設有一群 container cluster,而 container 不知道會在哪台機器啟動的時候,volume 設定就變很重要。另外架一台 storage 然後讓 container 機器設定 volume driver 存取 storage,這樣的設計就會非常有彈性。