国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 服務(wù)器 > Web服務(wù)器 > 正文

docker 數(shù)據(jù)卷之進(jìn)階篇

2024-09-01 13:54:03
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

筆者在《Docker 基礎(chǔ) : 數(shù)據(jù)管理》一文中介紹了 docker 數(shù)據(jù)卷(volume) 的基本用法。隨著使用的深入,筆者對(duì) docker 數(shù)據(jù)卷的理解與認(rèn)識(shí)也在不斷的增強(qiáng)。本文將在前文的基礎(chǔ)上介紹 docker 數(shù)據(jù)卷的原理及一些高級(jí)用法。如果您想先了解 docker 數(shù)據(jù)卷的基本概念與用法,請(qǐng)先移步這里。

為什么需要數(shù)據(jù)卷?

這得從 docker 容器的文件系統(tǒng)說(shuō)起。出于效率等一系列原因,docker 容器的文件系統(tǒng)在宿主機(jī)上存在的方式很復(fù)雜,這會(huì)帶來(lái)下面幾個(gè)問(wèn)題:

  1. 不能在宿主機(jī)上很方便地訪問(wèn)容器中的文件。
  2. 無(wú)法在多個(gè)容器之間共享數(shù)據(jù)。
  3. 當(dāng)容器刪除時(shí),容器中產(chǎn)生的數(shù)據(jù)將丟失。

為了解決這些問(wèn)題,docker 引入了數(shù)據(jù)卷(volume) 機(jī)制。數(shù)據(jù)卷是存在于一個(gè)或多個(gè)容器中的特定文件或文件夾,這個(gè)文件或文件夾以獨(dú)立于 docker 文件系統(tǒng)的形式存在于宿主機(jī)中。數(shù)據(jù)卷的最大特定是:其生存周期獨(dú)立于容器的生存周期。

使用數(shù)據(jù)卷的最佳場(chǎng)景

  1. 在多個(gè)容器之間共享數(shù)據(jù),多個(gè)容器可以同時(shí)以只讀或者讀寫的方式掛載同一個(gè)數(shù)據(jù)卷,從而共享數(shù)據(jù)卷中的數(shù)據(jù)。
  2. 當(dāng)宿主機(jī)不能保證一定存在某個(gè)目錄或一些固定路徑的文件時(shí),使用數(shù)據(jù)卷可以規(guī)避這種限制帶來(lái)的問(wèn)題。
  3. 當(dāng)你想把容器中的數(shù)據(jù)存儲(chǔ)在宿主機(jī)之外的地方時(shí),比如遠(yuǎn)程主機(jī)上或云存儲(chǔ)上。
  4. 當(dāng)你需要把容器數(shù)據(jù)在不同的宿主機(jī)之間備份、恢復(fù)或遷移時(shí),數(shù)據(jù)卷是很好的選擇。

docker volume 子命令

docker 專門提供了 volume 子命令來(lái)操作數(shù)據(jù)卷:
create 創(chuàng)建數(shù)據(jù)卷
inspect 顯示數(shù)據(jù)卷的詳細(xì)信息
ls 列出所有的數(shù)據(jù)卷
prune 刪除所有未使用的 volumes,并且有 -f 選項(xiàng)
rm 刪除一個(gè)或多個(gè)未使用的 volumes,并且有 -f 選項(xiàng)

先創(chuàng)建一個(gè)名稱為 hello 的數(shù)據(jù)卷并通過(guò) ls 命令進(jìn)行查看:

docker,數(shù)據(jù)卷

然后可以使用 inspect 命令看看數(shù)據(jù)卷 hello 的詳細(xì)信息:

docker,數(shù)據(jù)卷

在這里我們可以看到創(chuàng)建數(shù)據(jù)卷的時(shí)間;該數(shù)據(jù)卷使用的驅(qū)動(dòng)程序?yàn)槟J(rèn)的 "local",表示數(shù)據(jù)卷使用宿主機(jī)的本地存儲(chǔ);數(shù)據(jù)卷的掛載點(diǎn),默認(rèn)是本機(jī) /var/lib/docker/volumes 下的一個(gè)目錄。

最后我們可以使用 rm 或 prune 命令刪除數(shù)據(jù)卷,后面筆者會(huì)介紹一些實(shí)際使用中與數(shù)據(jù)卷的刪除有關(guān)的一些實(shí)踐。

使用 mount 語(yǔ)法掛載數(shù)據(jù)卷

之前我們使用 --volume(-v) 選項(xiàng)來(lái)掛載數(shù)據(jù)卷,現(xiàn)在 docker 提供了更強(qiáng)大的 --mount 選項(xiàng)來(lái)管理數(shù)據(jù)卷。mount 選項(xiàng)可以通過(guò)逗號(hào)分隔的多個(gè)鍵值對(duì)一次提供多個(gè)配置項(xiàng),因此 mount 選項(xiàng)可以提供比 volume 選項(xiàng)更詳細(xì)的配置。使用 mount 選項(xiàng)的常用

配置如下:

  1. type 指定掛載方式,我們這里用到的是 volume,其實(shí)還可以有 bind 和 tmpfs。
  2. volume-driver 指定掛載數(shù)據(jù)卷的驅(qū)動(dòng)程序,默認(rèn)值是 local。
  3. source 指定掛載的源,對(duì)于一個(gè)命名的數(shù)據(jù)卷,這里應(yīng)該指定這個(gè)數(shù)據(jù)卷的名稱。在使用時(shí)可以寫 source,也可以簡(jiǎn)寫為 src。
  4. destination 指定掛載的數(shù)據(jù)在容器中的路徑。在使用時(shí)可以寫 destination,也可以簡(jiǎn)寫為 dst 或 target。
  5. readonly 指定掛載的數(shù)據(jù)為只讀。
  6. volume-opt 可以指定多次,用來(lái)提高更多的 mount 相關(guān)的配置。

下面我們看個(gè)具體的例子:

$ docker volume create hello$ docker run -id --mount type=volume,source=hello,target=/world ubuntu /bin/bash

我們創(chuàng)建了名稱為 hello 的數(shù)據(jù)卷,然后把它掛在到容器中的 /world 目錄。通過(guò) inspect 命令查看容器的詳情中的 "Mounts" 信息可以驗(yàn)證實(shí)際的數(shù)據(jù)卷掛載結(jié)果 :

docker,數(shù)據(jù)卷

使用 volume driver 把數(shù)據(jù)存儲(chǔ)到其它地方

除了默認(rèn)的把數(shù)據(jù)卷中的數(shù)據(jù)存儲(chǔ)在宿主機(jī),docker 還允許我們通過(guò)指定 volume driver 的方式把數(shù)據(jù)卷中的數(shù)據(jù)存儲(chǔ)在其它的地方,比如 Azrue Storge 或 AWS 的 S3。

簡(jiǎn)單起見(jiàn),我們接下來(lái)的 demo 演示如何通過(guò) vieux/sshfs 驅(qū)動(dòng)把數(shù)據(jù)卷的存儲(chǔ)在其它的主機(jī)上。

docker 默認(rèn)是不安裝 vieux/sshfs 插件的,我們可以通過(guò)下面的命令進(jìn)行安裝:

$ docker plugin install --grant-all-permissions vieux/sshfs

然后通過(guò) vieux/sshfs 驅(qū)動(dòng)創(chuàng)建數(shù)據(jù)卷,并指定遠(yuǎn)程主機(jī)的登錄用戶名、密碼和數(shù)據(jù)存放目錄:

docker volume create --driver vieux/sshfs / -o sshcmd=nick@10.32.2.134:/home/nick/sshvolume / -o password=yourpassword / mysshvolume

注意,請(qǐng)確保你指定的遠(yuǎn)程主機(jī)上的掛載點(diǎn)目錄是存在的(demo 中是 /home/nick/sshvolume 目錄),否則在啟動(dòng)容器時(shí)會(huì)報(bào)錯(cuò)。
最后在啟動(dòng)容器時(shí)指定掛載這個(gè)數(shù)據(jù)卷:

docker run -id / --name testcon / --mount type=volume,volume-driver=vieux/sshfs,source=mysshvolume,target=/world / ubuntu /bin/bash

這就搞定了,你在容器中 /world 目錄下操作的文件都存儲(chǔ)在遠(yuǎn)程主機(jī)的 /home/nick/sshvolume 目錄中。進(jìn)入容器 testcon 然后在 /world 目錄中創(chuàng)建一個(gè)文件,然后打開(kāi)遠(yuǎn)程主機(jī)的 /home/nick/sshvolume 目錄進(jìn)行查看,你新建的文件是不是已經(jīng)出現(xiàn)在那里了!

數(shù)據(jù)卷原理

下圖描述了 docker 容器掛載數(shù)據(jù)的三種方式:

docker,數(shù)據(jù)卷

數(shù)據(jù)卷是完全被 docker 管理的,就像上圖中的黃色區(qū)域描述的一樣,docker 在宿主機(jī)的文件系統(tǒng)中找了個(gè)文件管理數(shù)據(jù)卷相關(guān)的數(shù)據(jù)。因此你可能根本不需要知道數(shù)據(jù)卷文件在宿主機(jī)上的存儲(chǔ)位置(事實(shí)上抱著刨根問(wèn)底的精神我們還是很想搞清楚它背后的工作原理!)。

docker 數(shù)據(jù)卷的本質(zhì)是容器中的一個(gè)特殊目錄。在容器創(chuàng)建的過(guò)程中,docker 會(huì)將宿主機(jī)上的指定目錄(一個(gè)以數(shù)據(jù)卷 ID 為名稱的目錄)掛載到容器中指定的目錄上。這里使用的掛載方式為綁定掛載(bind mount),所以掛載完成后的宿主機(jī)目錄和容器內(nèi)的目標(biāo)目錄表現(xiàn)一致。

比如我們執(zhí)行下面的命令創(chuàng)建數(shù)據(jù)卷 hello,并掛載到容器 testcon 的 /world 目錄:

$ docker volume create hello$ docker run -id --name testcon --mount type=volume,source=hello,target=/world ubuntu /bin/bash

實(shí)際上在容器的創(chuàng)建過(guò)程中,類似于在容器中執(zhí)行了下面的代碼:

// 將數(shù)據(jù)卷 hello 在宿主機(jī)上的目錄綁定掛載到 rootfs 中指定的掛載點(diǎn) /world 上mount("/var/lib/docker/volumes/hello/_data", "rootfs/world", "none", MS_BIND, NULL)

在處理完所有的 mount 操作之后(真正需要 docker 容器掛載的除了數(shù)據(jù)卷目錄還包括 rootfs,init-layer 里的內(nèi)容,/proc 設(shè)備等),docker 只需要通過(guò) chdir 和 pivot_root 切換進(jìn)程的根目錄到 rootfs 中,這樣容器內(nèi)部進(jìn)程就只能看見(jiàn)以 rootfs 為根的文件系統(tǒng)以及被 mount 到 rootfs 之下的各項(xiàng)目錄了。例如我們啟動(dòng)的 testcon 中的文件系統(tǒng)為:

docker,數(shù)據(jù)卷

下面我們介紹幾個(gè)數(shù)據(jù)卷在使用中比較常見(jiàn)的問(wèn)題。

數(shù)據(jù)的覆蓋問(wèn)題

  1. 如果掛載一個(gè)空的數(shù)據(jù)卷到容器中的一個(gè)非空目錄中,那么這個(gè)目錄下的文件會(huì)被復(fù)制到數(shù)據(jù)卷中。
  2. 如果掛載一個(gè)非空的數(shù)據(jù)卷到容器中的一個(gè)目錄中,那么容器中的目錄中會(huì)顯示數(shù)據(jù)卷中的數(shù)據(jù)。如果原來(lái)容器中的目錄中有數(shù)據(jù),那么這些原始數(shù)據(jù)會(huì)被隱藏掉。

這兩個(gè)規(guī)則都非常重要,靈活利用第一個(gè)規(guī)則可以幫助我們初始化數(shù)據(jù)卷中的內(nèi)容。掌握第二個(gè)規(guī)則可以保證掛載數(shù)據(jù)卷后的數(shù)據(jù)總是你期望的結(jié)果。

在 Dockerfile 中添加數(shù)據(jù)卷

在 Dockerfile 中我們可以使用 VOLUME 指令向容器添加數(shù)據(jù)卷:

VOLUME /data

在使用 docker build 命令生成鏡像并且以該鏡像啟動(dòng)容器時(shí)會(huì)掛載一個(gè)數(shù)據(jù)卷到 /data 目錄。根據(jù)我們已知的數(shù)據(jù)覆蓋規(guī)則,如果鏡像中存在 /data 目錄,這個(gè)目錄中的內(nèi)容將全部被復(fù)制到宿主機(jī)中對(duì)應(yīng)的目錄中,并且根據(jù)容器中的文件設(shè)置合適的權(quán)限和所有者。

注意,VOLUME 指令不能掛載主機(jī)中指定的目錄。這是為了保證 Dockerfile 的可一致性,因?yàn)椴荒鼙WC所有的宿主機(jī)都有對(duì)應(yīng)的目錄。

在實(shí)際的使用中,這里還有一個(gè)陷阱需要大家注意:在 Dockerfile 中使用 VOLUME 指令之后的代碼,如果嘗試對(duì)這個(gè)數(shù)據(jù)卷進(jìn)行修改,這些修改都不會(huì)生效!下面是一個(gè)這樣的例子:

FROM ubuntuRUN useradd nickVOLUME /dataRUN touch /data/test.txtRUN chown -R nick:nick /data

通過(guò)這個(gè) Dockerfile 創(chuàng)建鏡像并啟動(dòng)容器后,該容器中存在用戶 nick,并且能夠看到 /data 目錄掛載的數(shù)據(jù)卷。但是 /data 目錄內(nèi)并沒(méi)有文件 test.txt,更別說(shuō) test.txt 文件的所有者屬性了。要解釋這個(gè)現(xiàn)象需要我們了解通過(guò) Dockerfile 創(chuàng)建鏡像的過(guò)程:

Dockerfile 中除了 FROM 指令的每一行都是基于上一行生成的臨時(shí)鏡像運(yùn)行一個(gè)容器,執(zhí)行一條指令并執(zhí)行類似 docker commit 的命令得到一個(gè)新的鏡像。這條類似 docker commit 的命令不會(huì)對(duì)掛載的數(shù)據(jù)卷進(jìn)行保存。

所以上面的 Dockerfile 最后兩行執(zhí)行時(shí),都會(huì)在一個(gè)臨時(shí)的容器上掛載 /data,并對(duì)這個(gè)臨時(shí)的數(shù)據(jù)卷進(jìn)行操作,但是這一行指令執(zhí)行并提交后,這個(gè)臨時(shí)的數(shù)據(jù)卷并沒(méi)有被保存。因而我們最終通過(guò)鏡像創(chuàng)建的容器所掛載的數(shù)據(jù)卷是沒(méi)有被最后兩條指令操作過(guò)的。我們姑且叫它 "Dockerfile 中數(shù)據(jù)卷的初始化問(wèn)題"。

下面的寫法可以解決 Dockerfile 中數(shù)據(jù)卷的初始化問(wèn)題:

FROM ubuntuRUN useradd nickRUN mkdir /data && touch /data/test.txtRUN chown -R nick:nick /dataVOLUME /data

通過(guò)這個(gè) Dockerfile 創(chuàng)建鏡像并啟動(dòng)容器后,數(shù)據(jù)卷的初始化是符合預(yù)期的。這是由于在掛載數(shù)據(jù)卷時(shí),/data 已經(jīng)存在,/data 中的文件以及它們的權(quán)限和所有者設(shè)置會(huì)被復(fù)制到數(shù)據(jù)卷中。

還有另外一種方法可以解決 Dockerfile 中數(shù)據(jù)卷的初始化問(wèn)題。就是利用 CMD 指令和 ENTRYPOINT 指令的執(zhí)行特點(diǎn):與 RUN 指令在鏡像構(gòu)建過(guò)程中執(zhí)行不同,CMD 指令和 ENTRYPOINT 指令是在容器啟動(dòng)時(shí)執(zhí)行。因此使用下面的 Dockerfile 也可以達(dá)到對(duì)數(shù)據(jù)卷的初始化目的:

FROM ubuntuRUN useradd nickVOLUME /dataCMD touch /data/test.txt && chown -R nick:nick /data && /bin/bash

總結(jié)

數(shù)據(jù)卷解決了用戶數(shù)據(jù)的持久化問(wèn)題,能夠讓用戶在容器中產(chǎn)生的數(shù)據(jù)超出容器自身的生命周期。因此對(duì)于容器技術(shù)來(lái)說(shuō)掌握數(shù)據(jù)卷的使用非常必要。希望本文能夠幫助您理解數(shù)據(jù)卷相關(guān)的內(nèi)容。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到服務(wù)器教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 光泽县| 延津县| 二连浩特市| 大名县| 凤山县| 高州市| 昭通市| 开阳县| 华蓥市| 耒阳市| 沁阳市| 壤塘县| 巨野县| 丽水市| 曲松县| 方正县| 榕江县| 隆子县| 思茅市| 共和县| 武川县| 商河县| 筠连县| 平远县| 三台县| 册亨县| 祁阳县| 无棣县| 民县| 礼泉县| 醴陵市| 繁昌县| 陵水| 白山市| 彭阳县| 富阳市| 冷水江市| 扶风县| 湛江市| 龙门县| 湖南省|