前言
上一篇把常用命令演示了一遍,其中也提到容器的隔離性,預設情況下,容器內應用產生的資料都是由容器本身獨有,如果容器被刪除,對應的資料檔案就會跟著消失。從隔離性的角度來看,資料就應該和容器共存亡;但在實際用場景中,更多需要將資料持久化,即容器被刪除,資料也應該正常存在;另外也有很多場景需要容器之間共享資料,那該怎麼做呢,接下來說說容器資料卷。
正文
1. 手動儲存資料
通常手動有兩種方式,一是通過命令就行拷貝,二是將容器提交為映象。接下來通過拉取centos映象,執行演示
-
通過命令形式
主機和容器之間可以通過命令進行資料拷貝,也就是說,在容器刪除之前可以先進行資料拷貝,如下:
命令簡述:
docker run -it --name="mycentos" centos /bin/bash
,直接根據映象centos以互動模式啟動容器,容器名稱為mycentos,在容器內部執行/bin/bash命令進入到終端;具體命令在Docker小白到實戰之常用命令演示,通俗易懂這篇文章中已經詳細說明;這裡簡單回顧一下根據映象啟動容器流程,如圖:上圖簡述:在Docker執行啟動命令時,會先從本地查詢映象,如果沒有,就會去遠端倉庫搜尋並拉取到主機,然後主機就可以根據映象啟動容器;如果遠端倉庫也沒有找到映象,那麼就報錯。
好了,回到今天的話題,接著說拷貝資料;
現在通過centos映象啟動了一個容器(Linux系統),在上面建立一些檔案進行測試,如下:
現在如果將容器刪除,裡面對應的資料也會刪除,所以需要將對應的資料拷貝到主機上,如下:
docker cp bfb96a6afdbc:/usr/TestData /usr/TestDataHost
命令解析:- 語法:
docker cp SRC_PATH DEST_PATH
- bfb96a6afdbc:/usr/TestData對應的就是SRC_PATH ,表示源頭,即需要拷貝的目錄或檔案;bfb96a6afdbc這是容器ID,通過這種方式限定是某個容器內的資料檔案;
- /usr/TestDataHost對應的就是DEST_PATH,表示目標,即拷到什麼地方;
按照上面的語法規則,同樣可以將主機上的資料檔案拷貝到指定容器中,只是調換一下SRC_PATH 和DEST_PATH的位置即可,如下:
- 語法:
-
將容器提交為映象的方式
這種方式只能勉強說是一種備份,只是通過
docker commit
命令將容器提交為映象,從而達到備份資料的作用;但很明顯能感覺到不靈活,資料還是在容器內。關於
docker commit
命令上次已經說過,這裡就不重複截圖啦。
以上兩種方式都不是很好的選擇,首先在時效上也不能及時備份,另外通過手動這種操作很明顯效率不高,還容易出錯;更重要的是苦了小夥伴們,所以必須把自動安排起來;手動這種方式,根據情況偶爾用用就可以啦。
2. 容器資料卷解放雙手
2.1 簡單理解容器資料卷
資料卷可以理解為目錄或檔案,設計目的就是為了資料的持久化和共享;
掛載資料卷的容器,稱為資料卷容器;資料卷完全獨立於容器的生存週期,所以容器刪除時,對應掛載的資料卷不會被刪除。
通過將容器內的目錄掛載到主機上面,就可以讓資料實時同步,不管是主機改動,還是容器裡有變動,都會同步更新。
2.2 實操演示
這裡先用命令的方式進行演示,關於Dockerfile中的應用會在後續的章節中說到。
docker run
命令中-v的選項在上次沒說,就是故意留到這裡單獨分享;直接在啟動容器的時候掛載;語法主要有如下幾種方式:
# 指定具體的主機路徑和容器內的路徑
docker run -v /宿主機路徑:容器內路徑 映象名
# 指定容器內的路徑,docker預設自動指定主機路徑
docker run -v 容器內路徑 映象名
# 指定容器內的路徑,並指定一個名字,主機路徑docker自動指定
docker run -v 卷名:容器內路徑 映象名
-
匿名掛載:在掛載時不指定名稱,會自動生成一個名稱
指定主機目錄
命令解析如下圖:
# docker run -it --name="容器名稱" -v 主機絕對路徑:容器絕對路徑 映象名稱 docker run -it --name="TestVolumeCentos" -v /usr/TestDataHost/DataVolumeTest:/usr/TestVolumeData centos
現在已經將容器內的目錄掛載到主機上,接下來感受一下資料同步:
通過上圖演示可以看到,不管是在主機還是在容器中修改資料,都能及時同步更新; 容器停止之後,主機更新資料,容器再啟動,修改的資料也會同步到容器; 容器刪除,掛載的資料不會被刪除,還是在主機中,這就是我們想要的。
可以通過
docker inspect 容器
命令檢視容器的詳細資訊,其中就有掛載卷的詳細資訊,如下部分截圖:不指定主機目錄
很多時候,我們不喜歡自己指定主機目錄,而是由Docker自動指定,所以通常我們只指定容器內目錄,如下:
看看Docker指定的主機路徑在哪,還是通過
docker inspect 容器ID
檢視詳情,如下:看看剛才在容器操作的檔案資料是否同步過來:
預設情況,docker都會將掛載的主機目錄指定到如上圖的目錄中。
可以通過
docker volume ls
檢視主機掛載的資料卷資訊,如下:通過上圖可以看到,名稱不直觀,看不懂,所以更多時候都會在掛載的時候指定一個名稱,即具名掛載。
-
具名掛載:在掛載時指定一個名稱。
這裡除了掛載的時候是指定名稱掛載,之後的操作和效果都一樣,這裡就不重複截圖了; 需要注意的是這種方式和指定主機的命令很像,指定路徑那種形式,冒號前面是路徑,如下:
2.3 容器間傳遞資料
資料卷其實還可以通過容器繼承方式進行掛載,從而實現容器之間的資料共享,如下:
關鍵命令解析:
-
先啟動一個具名掛載的容器TestVolumesFromCentos,如下命令:
docker run -it --name="TestVolumesFromCentos" -v testVolumesFrom:/usr/TestVolumeData centos
-
在啟動另一個容器TestVolumesFromCentos2,掛載卷繼承於TestVolumesFromCentos,如下命令:
docker run -it --name="TestVolumesFromCentos2" --volumes-from TestVolumesFromCentos centos
--volumes-from 後指定繼承於哪個容器。
現在不管在哪個容器中變更資料,都會實時同步到其他容器中,從而達成了容器資料的共享和實時同步。
通過docker inspect 容器ID
看兩個容器的掛載詳情都一樣,截其中一個容器如下:
其實在指定掛載的時候還可以限制容器的操作許可權,比如在容器內的掛載目錄下,可以限制容器內只讀或可讀寫,如下:
ro:代表只讀;
rw:代表讀寫;
好了,關於容器資料卷就說到這吧,是不是聽起來名字高大上,其實就是對檔案或目錄的操作。
2.4 redis安裝實戰
關於Redis安裝在Docker中很簡單,直接執行命令即可,由於之前拉取過redis的映象,所以就直接啟動容器了,如果本地沒有映象,就會去遠端倉庫拉取。
上圖中可以看到,預設情況下,redis的映象將容器內的/data目錄掛載到這個主機上,而這個目錄就是redis資料存放的目錄,這樣就達到Redis的持久化。
對於Redis而言,很多時候需要修改配置檔案,總不能每次修改都要到容器內更改,我們可以將配置檔案放在已掛載的目錄中,然後指定啟動,也可以另外針對配置檔案再加一個掛載,如下:
執行命令前,需要將配置檔案提前放在主機的這個/usr/TestDataHost/redisconf目錄中。
docker run -d -v /usr/TestDataHost/redisconf:/usr/local/etc/redis --name myredisconfigtest redis redis-server /usr/local/etc/redis/redis.conf
通過docker inspect 容器
看看掛載情況,如下:
通過掛載之後,如果需要修改配置檔案,只需要在主機上修改配置檔案內容即可。
總結
關於容器資料卷就說到這吧,對於容器是不是感覺很給力,既有隔離又有共享,滿足各種場景。下一篇來說說Dockerfile,製作屬於自己的映象,關注“Code綜藝圈”,和我一起學習吧;