溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

docker數(shù)據(jù)卷如何掛載

發(fā)布時間:2022-05-20 15:36:31 來源:億速云 閱讀:206 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“docker數(shù)據(jù)卷如何掛載”,在日常操作中,相信很多人在docker數(shù)據(jù)卷如何掛載問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”docker數(shù)據(jù)卷如何掛載”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

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

這得從 docker 容器的文件系統(tǒng)說起。出于效率等一系列原因,docker 容器的文件系統(tǒng)在宿主機上存在的方式很復雜,這會帶來下面幾個問題:

  1. 不能在宿主機上很方便地訪問容器中的文件。

  2. 無法在多個容器之間共享數(shù)據(jù)。

  3. 當容器刪除時,容器中產(chǎn)生的數(shù)據(jù)將丟失。

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

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

  1. 在多個容器之間共享數(shù)據(jù),多個容器可以同時以只讀或者讀寫的方式掛載同一個數(shù)據(jù)卷,從而共享數(shù)據(jù)卷中的數(shù)據(jù)。

  2. 當宿主機不能保證一定存在某個目錄或一些固定路徑的文件時,使用數(shù)據(jù)卷可以規(guī)避這種限制帶來的問題。

  3. 當你想把容器中的數(shù)據(jù)存儲在宿主機之外的地方時,比如遠程主機上或云存儲上。

  4. 當你需要把容器數(shù)據(jù)在不同的宿主機之間備份、恢復或遷移時,數(shù)據(jù)卷是很好的選擇。

docker volume 子命令

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

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

docker數(shù)據(jù)卷如何掛載

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

docker數(shù)據(jù)卷如何掛載

在這里我們可以看到創(chuàng)建數(shù)據(jù)卷的時間;該數(shù)據(jù)卷使用的驅(qū)動程序為默認的 "local",表示數(shù)據(jù)卷使用宿主機的本地存儲;數(shù)據(jù)卷的掛載點,默認是本機 /var/lib/docker/volumes 下的一個目錄。

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

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

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

配置如下:

  1. type 指定掛載方式,我們這里用到的是 volume,其實還可以有 bind 和 tmpfs。

  2. volume-driver 指定掛載數(shù)據(jù)卷的驅(qū)動程序,默認值是 local。

  3. source 指定掛載的源,對于一個命名的數(shù)據(jù)卷,這里應(yīng)該指定這個數(shù)據(jù)卷的名稱。在使用時可以寫 source,也可以簡寫為 src。

  4. destination 指定掛載的數(shù)據(jù)在容器中的路徑。在使用時可以寫 destination,也可以簡寫為 dst 或 target。

  5. readonly 指定掛載的數(shù)據(jù)為只讀。

  6. volume-opt 可以指定多次,用來提高更多的 mount 相關(guān)的配置。

下面我們看個具體的例子:

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

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

docker數(shù)據(jù)卷如何掛載

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

除了默認的把數(shù)據(jù)卷中的數(shù)據(jù)存儲在宿主機,docker 還允許我們通過指定 volume driver 的方式把數(shù)據(jù)卷中的數(shù)據(jù)存儲在其它的地方,比如 azrue storge 或 aws 的 s3。

簡單起見,我們接下來的 demo 演示如何通過 vieux/sshfs 驅(qū)動把數(shù)據(jù)卷的存儲在其它的主機上。

docker 默認是不安裝 vieux/sshfs 插件的,我們可以通過下面的命令進行安裝:

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

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

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

注意,請確保你指定的遠程主機上的掛載點目錄是存在的(demo 中是 /home/nick/sshvolume 目錄),否則在啟動容器時會報錯。
最后在啟動容器時指定掛載這個數(shù)據(jù)卷:

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

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

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

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

docker數(shù)據(jù)卷如何掛載

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

docker 數(shù)據(jù)卷的本質(zhì)是容器中的一個特殊目錄。在容器創(chuàng)建的過程中,docker 會將宿主機上的指定目錄(一個以數(shù)據(jù)卷 id 為名稱的目錄)掛載到容器中指定的目錄上。這里使用的掛載方式為綁定掛載(bind mount),所以掛載完成后的宿主機目錄和容器內(nèi)的目標目錄表現(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

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

// 將數(shù)據(jù)卷 hello 在宿主機上的目錄綁定掛載到 rootfs 中指定的掛載點 /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 只需要通過 chdir 和 pivot_root 切換進程的根目錄到 rootfs 中,這樣容器內(nèi)部進程就只能看見以 rootfs 為根的文件系統(tǒng)以及被 mount 到 rootfs 之下的各項目錄了。例如我們啟動的 testcon 中的文件系統(tǒng)為:

docker數(shù)據(jù)卷如何掛載

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

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

  1. 如果掛載一個空的數(shù)據(jù)卷到容器中的一個非空目錄中,那么這個目錄下的文件會被復制到數(shù)據(jù)卷中。

  2. 如果掛載一個非空的數(shù)據(jù)卷到容器中的一個目錄中,那么容器中的目錄中會顯示數(shù)據(jù)卷中的數(shù)據(jù)。如果原來容器中的目錄中有數(shù)據(jù),那么這些原始數(shù)據(jù)會被隱藏掉。

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

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

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

volume /data

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

注意,volume 指令不能掛載主機中指定的目錄。這是為了保證 dockerfile 的可一致性,因為不能保證所有的宿主機都有對應(yīng)的目錄。

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

from ubuntu
run useradd nick
volume /data
run touch /data/test.txt
run chown -r nick:nick /data

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

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

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

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

from ubuntu
run useradd nick
run mkdir /data && touch /data/test.txt
run chown -r nick:nick /data
volume /data

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

還有另外一種方法可以解決 dockerfile 中數(shù)據(jù)卷的初始化問題。就是利用 cmd 指令和 entrypoint 指令的執(zhí)行特點:與 run 指令在鏡像構(gòu)建過程中執(zhí)行不同,cmd 指令和 entrypoint 指令是在容器啟動時執(zhí)行。因此使用下面的 dockerfile 也可以達到對數(shù)據(jù)卷的初始化目的:

from ubuntu
run useradd nick
volume /data
cmd touch /data/test.txt && chown -r nick:nick /data && /bin/bash

到此,關(guān)于“docker數(shù)據(jù)卷如何掛載”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI