Docker之實(shí)現(xiàn)掛載的三種方式匯總
Docker實(shí)現(xiàn)掛載的方式
在介紹VOLUME指令之前,我們來看下如下場景需求:
1.容器是基于鏡像創(chuàng)建的,最后的容器文件系統(tǒng)包括鏡像的只讀層+可寫層,容器中的進(jìn)程操作的數(shù)據(jù)持久化都是保存在容器的可寫層上。一旦容器刪除后,這些數(shù)據(jù)就沒了,除非我們?nèi)斯浞菹聛恚ɑ蛘呋谌萜鲃?chuàng)建新的鏡像)。能否可以讓容器進(jìn)程持久化的數(shù)據(jù)保存在主機(jī)上呢?這樣即使容器刪除了,數(shù)據(jù)還在。
2. 當(dāng)我們在開發(fā)一個web應(yīng)用時,開發(fā)環(huán)境是在主機(jī)本地,但運(yùn)行測試環(huán)境是放在docker容器上。這樣的話,我在主機(jī)上修改文件(如html,js等)后,需要再同步到容器中。這顯然比較麻煩。
3. 多個容器運(yùn)行一組相關(guān)聯(lián)的服務(wù),如果他們要共享一些數(shù)據(jù)怎么辦?
對于這些問題,我們當(dāng)然能想到各種解決方案。而docker本身提供了一種機(jī)制,可以將主機(jī)上的某個目錄與容器的某個目錄(稱為掛載點(diǎn)、或者叫卷)關(guān)聯(lián)起來,容器上的掛載點(diǎn)下的內(nèi)容就是主機(jī)的這個目錄下的內(nèi)容,這類似linux系統(tǒng)下mount的機(jī)制。 這樣的話,我們修改主機(jī)上該目錄的內(nèi)容時,不需要同步容器,對容器來說是立即生效的。 掛載點(diǎn)可以讓多個容器共享。
下面我們來介紹具體的實(shí)現(xiàn)機(jī)制。
一、通過docker run命令
1.運(yùn)行命令:docker run --name test -it -v /home/xqh/myimage:/data ubuntu /bin/bash
其中的 -v 標(biāo)記 在容器中設(shè)置了一個掛載點(diǎn) /data(就是容器中的一個目錄),并將主機(jī)上的 /home/xqh/myimage 目錄中的內(nèi)容關(guān)聯(lián)到 /data下。
這樣在容器中對/data目錄下的操作,還是在主機(jī)上對/home/xqh/myimage的操作,都是完全實(shí)時同步的,因?yàn)檫@兩個目錄實(shí)際都是指向主機(jī)目錄。
2.運(yùn)行命令:docker run --name test1 -it -v /data ubuntu /bin/bash
上面-v的標(biāo)記只設(shè)置了容器的掛載點(diǎn),并沒有指定關(guān)聯(lián)的主機(jī)目錄。這時docker會自動綁定主機(jī)上的一個目錄。通過docker inspect 命令可以查看到。
xqh@ubuntu:~/myimage$ docker inspect test1 [ { ? ? "Id": "1fd6c2c4bc545163d8c5c5b02d60052ea41900a781a82c20a8f02059cb82c30c", ............................. ? ? "Mounts": [ ? ? ? ? { ? ? ? ? ? ? "Name": "0ab0aaf0d6ef391cb68b72bd8c43216a8f8ae9205f0ae941ef16ebe32dc9fc01", ? ? ? ? ? ? "Source": "/var/lib/docker/volumes/0ab0aaf0d6ef391cb68b72bd8c43216a8f8ae9205f0ae941ef16ebe32dc9fc01/_data", ? ? ? ? ? ? "Destination": "/data", ? ? ? ? ? ? "Driver": "local", ? ? ? ? ? ? "Mode": "", ? ? ? ? ? ? "RW": true ? ? ? ? } ? ? ],
上面 Mounts下的每條信息記錄了容器上一個掛載點(diǎn)的信息,“Destination” 值是容器的掛載點(diǎn),"Source"值是對應(yīng)的主機(jī)目錄??梢钥闯鲞@種方式對應(yīng)的主機(jī)目錄是自動創(chuàng)建的,其目的不是讓在主機(jī)上修改,而是讓多個容器共享。
二、通過dockerfile創(chuàng)建掛載點(diǎn)
上面介紹的通過docker run命令的-v標(biāo)識創(chuàng)建的掛載點(diǎn)只能對創(chuàng)建的容器有效。通過dockerfile的 VOLUME 指令可以在鏡像中創(chuàng)建掛載點(diǎn),這樣只要通過該鏡像創(chuàng)建的容器都有了掛載點(diǎn)。
還有一個區(qū)別是,通過 VOLUME 指令創(chuàng)建的掛載點(diǎn),無法指定主機(jī)上對應(yīng)的目錄,是自動生成的。
#test FROM ubuntu MAINTAINER hello1 VOLUME ["/data1","/data2"]
上面的dockfile文件通過VOLUME指令指定了兩個掛載點(diǎn) /data1 和 /data2.
我們通過docker inspect 查看通過該dockerfile創(chuàng)建的鏡像生成的容器,可以看到如下信息
"Mounts": [ ? ? { ? ? ? ? "Name": "d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21", ? ? ? ? "Source": "/var/lib/docker/volumes/d411f6b8f17f4418629d4e5a1ab69679dee369b39e13bb68bed77aa4a0d12d21/_data", ? ? ? ? "Destination": "/data1", ? ? ? ? "Driver": "local", ? ? ? ? "Mode": "", ? ? ? ? "RW": true ? ? }, ? ? { ? ? ? ? "Name": "6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36", ? ? ? ? "Source": "/var/lib/docker/volumes/6d3badcf47c4ac5955deda6f6ae56f4aaf1037a871275f46220c14ebd762fc36/_data", ? ? ? ? "Destination": "/data2", ? ? ? ? "Driver": "local", ? ? ? ? "Mode": "", ? ? ? ? "RW": true ? ? } ],
可以看到兩個掛載點(diǎn)的信息。
三、容器共享卷(掛載點(diǎn))
下面我們創(chuàng)建另一個容器可以和test1(已經(jīng)創(chuàng)建好的容器)共享 /data1 和 /data2卷,這是在 docker run中使用 --volumes-from標(biāo)記,如:
可以是來源不同鏡像,如:
docker run --name test2 -it --volumes-from test1 ubuntu /bin/bash
也可以是同一鏡像,如:
docker run --name test3 -it --volumes-from test1 myimage /bin/bash
上面的三個容器 test1 , test2 , test3 均有 /data1 和 /data2 兩個目錄,且目錄中內(nèi)容是共享的,任何一個容器修改了內(nèi)容,別的容器都能獲取到。
四、最佳實(shí)踐:數(shù)據(jù)容器
如果多個容器需要共享數(shù)據(jù)(如持久化數(shù)據(jù)庫、配置文件或者數(shù)據(jù)文件等),可以考慮創(chuàng)建一個特定的數(shù)據(jù)容器,該容器有1個或多個卷。
其它容器通過–volumes-from 來共享這個數(shù)據(jù)容器的卷。
因?yàn)槿萜鞯木肀举|(zhì)上對應(yīng)主機(jī)上的目錄,所以這個數(shù)據(jù)容器也不需要啟動。
如: docker run --name dbdata myimage echo “data container”
說明:有個卷,容器之間的數(shù)據(jù)共享比較方便,但也有很多問題需要解決,如權(quán)限控制、數(shù)據(jù)的備份、卷的刪除等。以后在介紹。
關(guān)于Docker中掛載的解釋
現(xiàn)在有這么一個命令:
docker run -p 33061:3306 --name mysql ?--restart=always -e MYSQL_ROOT_PASSWORD=pisen ?-v /etc/localtime:/etc/localtime:ro ?-v /etc/timezone:/etc/timezone:ro ?-d mysql:5.7
因?yàn)橹匾f掛載的問題,就單獨(dú)揪出來參數(shù)來說
-v /etc/localtime:/etc/localtime:ro
就是將 宿主機(jī)的/etc/localtime文件掛載到容器的/etc/localtime 文件,并且容器內(nèi)的/etc/localtime文件設(shè)置為只讀(:ro)
實(shí)際的效果就是mysql容器啟動后,時間時區(qū)的設(shè)置,使用的就是宿主機(jī)的 /etc/localtime 文件內(nèi)設(shè)置的內(nèi)容起作用。
如果沒有設(shè)置只讀的情況下,該掛載實(shí)現(xiàn)的效果是:
情況1:使用echo命令去修改
echo 'lq' > timezone
無論更改宿主機(jī)上的/etc/localtime文件內(nèi)容還是修改容器內(nèi)的/etc/localtime文件內(nèi)容,都會影響到對方?! ?/p>
情況2:使用vi命令去修改
vi timezone
則無論修改哪邊都不會影響到另外一方的文件內(nèi)容。
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
docker容器狀態(tài)出現(xiàn)Exit(1)的問題及解決
這篇文章主要介紹了docker容器狀態(tài)出現(xiàn)Exit(1)的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06Docker 數(shù)據(jù)卷,數(shù)據(jù)卷容器詳細(xì)介紹
這篇文章主要介紹了 Docker 數(shù)據(jù)卷,數(shù)據(jù)卷容器詳細(xì)介紹的相關(guān)資料,這里對Docker 數(shù)據(jù)卷,數(shù)據(jù)卷容器的感念及相關(guān)操作進(jìn)行了介紹,需要的朋友可以參考下2016-11-11docker安裝tomcat并部署Springboot項(xiàng)目war包的方法
這篇文章主要介紹了docker安裝tomcat并部署Springboot項(xiàng)目war包的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11