引言
docker的鏡像是由多個只讀的文件系統疊加在一起形成的。當我們在我啟動一個容器的時候,docker會加載這些只讀層並在這些只讀層的上面(棧頂)增加一個讀寫層。這時如果修改正在運行的容器中已有的文件,那么這個文件將會從只讀層復制到讀寫層。該文件的只讀版本還在,只是被上面讀寫層的該文件的副本隱藏。當刪除docker,或者重新啟動時,之前的更改將會消失。在Docker中,只讀層及在頂部的讀寫層的組合被稱為Union File System(聯合文件系統)。
為了很好的實現數據保存和數據共享,Docker提出了Volume這個概念,簡單的說就是繞過默認的聯合文件系統,而以正常的文件或者目錄的形式存在於宿主機上。又被稱作數據卷。
Volume的作用
- 通過數據卷可以在容器之間實現共享和重用
- 對數據卷的修改會立馬生效(非常適合作為開發環境)
- 對數據卷的更新,不會影響鏡像
- 卷會一直存在,直到沒有容器使用
初始化Volume
在使用docker run的時候我們可以通過 -v 來創建一個數據卷並掛載到容器上,在一次run中多次使用可以掛載多個容器。
如果使用Dockerfile方式進行初始化時可以使用 VOLUME 來添加一個或者多個新的卷到由該鏡像創建的任意容器。
創建一個數據卷
上面的命令的意思是,我們創建了一個名稱為shanlei-nginx的容器,將本機的8080端口映射到容器中nginx服務器的默認web訪問端口80下,創建一個數據卷,並掛載到容器的/usr/share/nginx/html目錄下。
這時我們就可以繞過聯合文件系統,直接在主機上操作該目錄了,任何在該鏡像/usr/share/nginx/html下的文件都會被復制到Volume。
我們可以通過docker inspect指令找到Volume在主機上的存儲位置
docker inspect指令后面的參數可以跟容器名稱。通過這個命令我們可以獲得容器所有的相關信息。我們需要看這一部分
這說明docker把本機的“Source”指向目錄,也就是
掛載到了容器的“Destination”指向的目錄。
在Linux中我們可以直接進入“Source”指向的路徑(注意在訪問該目錄時可能會有權限問題)
只要將主機的目錄掛載到容器的目錄上,那改變就會立即生效。在Dockerfile中我們可以通過VOLUME達到相同的目的
目錄作為數據卷
通過-v標識可以將主機的目錄掛載到容器中去
上面的命令將本機的$PWD/html目錄掛載到容器的/usr/share/nginx/html目錄。$PWD在是一個系統環境變量,指代當前目錄環境。這個功能在進行測試的時候十分方便,比如用戶可以放置一些程序到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動為你創建它。
注意:Dockerfile中不支持這種語法.
docker掛載數據卷的默認權限是讀寫,當然我們可以通過指令:ro指定為只讀。
在我的本機主機的$PWD/html中有一個index.html文件,內容如下:
我們運行上面的命令,並將本機8080端口映射到容器中nginx服務器的默認web端口80下,現在我們來訪問localhost:8080
現在我們修改本機下的$PWD/html/index.html
訪問localhost:8080
文件作為數據卷
我們也可以使用-v指令從主機掛載單個文件到容器中去
當修改本機$PWD/html/index.html時,容器中的/usr/share/nginx/html/index.html也會隨之變化。效果和上面相同,在這里就不做贅述了。
注意:如果直接掛載一個文件,很多文件編輯工具,包括 vi 或者 sed --in-place ,可能會造成文件 inode的改變,從 Docker 1.1 .0起,這會導致報錯誤信息。所以最簡單的辦法就直接掛載文件的父目錄。
數據共享
如果想要實現容器間的數據共享,那么需要授權一個容器訪問另一個容器的Volume。我們可以在使用docker run時使用-volumes-from參數來進行指定。
注意:值得注意的是不管shanlei-nginx是否運行,它都會起作用。只要有容器連接Volume,它就不會被刪除。
數據卷容器
如果我們有一些持續更新的數據需要在容器之間共享,最好創建數據卷容器。常見的使用場景是使用純數據容器來持久化數據庫、配置文件或者數據文件等。
數據卷容器,其實就是一個正常的容器,專門用來提供數據卷供其它容器掛載的。
首先我們需要先創建一個數據卷容器
然后通過--volumes-from指令參數來掛載 dbdata 容器中的數據卷。
當然,我們也可以使用多個 --volumes-from 參數來從多個容器掛載多個數據卷。 也可以從其他已經掛載了數據卷的容器
來掛載數據卷。
現在我們進入容器中查看數據卷容器是否掛載成功
說明數據卷容器掛載已經成功了。
注意:如果刪除了掛載的容器(包括 dbdata、db1 和 db2等),數據卷並不會被自動刪除。如果要刪除一個數據卷,必
須在刪除最后一個還掛載着它的容器時使用 docker rm -v 命令來指定同時刪除關聯的容器。
備份和恢復
我們可以利用數據卷對其中的數據進行進行備份、恢復和遷移。
首先使用 --volumes-from 標記來創建一個加載 dbdata 容器卷的容器,並從本地主機掛載當前到容器的 /backup 目錄。命令如下:
容器啟動后,使用了 tar 命令來將 dbdata 卷備份為本地的 /backup/backup.tar 。
恢復
如果要恢復數據到一個容器,首先創建一個帶有數據卷的容器 dbdata2。
然后創建另一個容器,掛載 dbdata2 的容器,並使用 untar 解壓備份文件到掛載的容器卷中。
以上