程式扎記: Docker Practice - Volume Management

標籤

2015年5月26日 星期二

Docker Practice - Volume Management

(Source)

Docker 資料管理#

(P45) 這一章介紹如何在 Docker 內部以及容器之間管理資料,在容器中管理資料主要有兩種方式:
  • 資料卷(Data volumes)
  • 資料卷容器(Data volume containers)

資料卷#

資料卷是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,可以提供很多有用的特性:
  • 資料卷可以在容器之間共享和重用
  • 對資料卷的修改會立馬生效
  • 對資料卷的更新,不會影響映像檔
  • 卷會一直存在,直到沒有容器使用

資料卷的使用,類似於 Linux 下對目錄或檔案進行 mount。

建立一個資料卷#

在用 docker run 命令的時候,使用 -v 標記來建立一個資料卷並掛載到容器裡。在一次 run 中多次使用可以掛載多個資料卷。下面建立一個 web 容器,並載入一個資料卷到容器的 /webapp 目錄:
// -P, --publish-all=false Publish all exposed ports to the host interfaces 
// -d, --detach=false Detached mode: Run container in the background, print new container id 
// --name="" Assign a name to the container 
// -v, --volume= Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container) 

# docker run -d -P --name web -v /webapp training/webapp python app.py

*注意:也可以在 Dockerfile 中使用 VOLUME 來新增一個或者多個新的卷到由該映像檔建立的任意容器。

掛載一個主機目錄作為資料卷#

使用 -v 標記也可以指定掛載一個本地主機的目錄到容器中去:
# docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py

上面的命令掛載主機的 /src/webapp 目錄到容器的 /opt/webapp 目錄。這個功能在進行測試的時候十分方便,比如使用者可以放置一些程式到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動為你建立它

*注意:Dockerfile 中不支援這種用法,這是因為 Dockerfile 是為了移植和分享用的。然而,不同作業系統的路徑格式不一樣,所以目前還不能支援。

Docker 掛載資料卷的預設權限是讀寫,使用者也可以透過 :ro 指定為唯讀:
# docker run -d -P --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py

掛載一個本地主機檔案作為資料卷#

-v 標記也可以從主機掛載單個檔案到容器中:
# docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash

這樣就可以記錄在容器輸入過的命令了。

*注意:如果直接掛載一個檔案,很多檔案編輯工具,包括 vi 或者 sed --in-place ,可能會造成檔案 inode 的改變,從 Docker 1.1 .0 起,這會導致報錯誤訊息。所以最簡單的辦法就直接掛載檔案的父目錄。

資料卷容器#

如果你有一些持續更新的資料需要在容器之間共享,最好的辦法是建立資料卷容器。

資料卷容器,其實就是一個正常的容器,專門用來提供資料卷供其它容器掛載的。

首先,建立一個命名的資料卷容器 dbdata:
# docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container

然後,在其他容器中使用 --volumes-from 來掛載 dbdata 容器中的資料卷。
# docker run -itd --volumes-from dbdata --name db1 training/postgres 
# docker run -itd --volumes-from dbdata --name db2 training/postgres 
# docker ps | awk 'BEGIN {FS=" "} NR > 1 {print $1 " " $11}' // Print db1, db2 Container ID 
5e7da1a18751 db2 
2c04250fa172 db1 

# docker attach db1 // 連接 db1 的 shell 
root@2c04250fa172:/# echo "test" > /dbdata/log // 在共用的資料卷建立資料 
root@2c04250fa172:/# // Ctrl+p -> Ctrl+q 退出 db1 Container 
# docker attach db2 // 連接 db2 的 shell 
# cat /dbdata/log // 確認 db1 的資料可以在 db2 看到! 
test 
root@5e7da1a18751:/# // Ctrl+p -> Ctrl+q 退出 db2 Container 
# docker run -it --volumes-from dbdata --name db3 training/postgres /bin/bash 
root@3cad19482d05:/# cat /dbdata/log // 新建的 db3 Container 也可以看到共用的資料卷上的資料 
test

還可以使用多個 --volumes-from 參數來從多個容器掛載多個資料卷。 也可以從其他已經掛載了容器卷的容器來掛載資料卷。
# docker run -d --name db4 --volumes-from db1 training/postgres

*注意:使用 --volumes-from 參數所掛載資料卷的容器自己並不需要保持在執行狀態。

如果刪除了掛載的容器(包括 dbdata、db1 和 db2),資料卷並不會被自動刪除。如果要刪除一個資料卷,必須在刪除最後一個還掛載著它的容器時使用 docker rm -v 命令來指定同時刪除關聯的容器。 這可以讓使用者在容器之間升級和移動資料卷。具體的操作將在下一節中進行講解。

利用資料卷容器來備份、恢復、遷移資料卷#

可以利用資料卷對其中的資料進行進行備份、恢復和遷移。
備份
首先使用 --volumes-from 標記來建立一個載入 dbdata 容器卷的容器,並從本地主機掛載當前到容器的 /backup 目錄。命令以下:
# docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

容器啟動後,使用了 tar 命令來將 dbdata 卷備份為本地的 /backup/backup.tar 

恢復
如果要恢復資料到一個容器,首先建立一個帶有資料卷的容器 dbdata2:
# docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

然後建立另一個容器,掛載 dbdata2 的容器,並使用 untar 解壓備份檔案到掛載的容器卷中:
# docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf /backup/backup.tar

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!