將主機目錄掛載到 Docker 容器中
除了其他功能外,Docker 還提供了與主機作業系統和容器檔案系統一起工作的工具。這些功能之一是能夠將資料持久儲存在容器中,並通過將目錄掛載到 Docker 容器在容器之間共享資料。
將目錄掛載到 Docker 容器在開發環境和生產環境中很有幫助。除了建立依賴於主機系統目錄的服務外,這還可以確保在 Docker 容器被破壞時不會破壞整個檔案系統。
假設我們想構建一個新版本的容器。在這種情況下,直接將目錄掛載到 Docker 容器會啟用熱過載。
本文要求 Docker 已正確設定並具有 Docker 映像和容器。無論我們是在 wsl 還是 Linux 上執行 Docker,這都會起作用。
使用繫結掛載將主機目錄掛載到 Docker 容器中
繫結掛載是最早的解決方案之一,它允許我們通過將 Docker 容器掛載到主機系統上的目錄來持久化資料。這些將使我們能夠通過引用目標目錄的絕對檔案路徑來引用目錄。
在這種情況下,Docker 不受此目錄的控制,這與 Docker 卷的情況不同。Docker 卷在 Docker 管理的 Docker 儲存系統中建立一個目錄。
除此之外,與 Docker 卷不同,我們無法通過 Docker CLI 或 Docker API 直接管理掛載到容器的目錄。但是,Docker 掛載在 MAC 或 windows 等主機中具有高效能,在這些主機中 Docker 卷的效能稍顯遜色。
我們還應該注意,使用繫結掛載將容器掛載到目錄肯定會增加容器的大小。
我們可以在啟動容器時使用兩個標誌將目錄掛載到容器。其中包括 -v
和 --mount
標誌。
使用 -v
或 --volume
標誌將主機目錄裝載到 Docker 容器中
它由三個欄位組成,這些欄位應始終按正確的順序排列並用冒號分隔。這些包括:
- 我們要掛載的主機上目錄的路徑。
- 我們應該掛載這個目錄的容器中目錄的路徑。
- 其他可選選項如
ro
指定只讀模式。
docker run -t -i -v <host_dir>:<container_dir
一旦我們確定了我們要一起掛載的主機和容器目錄,我們就可以實現上述命令。但是,我們不能對敏感檔案進行修改。
這是因為掛載讓我們可以訪問敏感檔案,如果被篡改,可能會導致我們的系統發生致命故障。
在這種情況下,我們將使用官方的 ruby 映象來建立容器並掛載目錄。我們使用目錄名稱命名指令碼,與 Docker 容器相同。
isaac@DESKTOP-HV44HT6:~/isaac$ docker run -it --rm -v$HOME/Desktop/scripts:/scripts --name scripts ruby bash
Unable to find image 'ruby:latest' locally
latest: Pulling from library/ruby
e4d61adff207: Pull complete
4ff1945c672b: Pull complete
ff5b10aec998: Pull complete
12de8c754e45: Pull complete
ada1762e7602: Pull complete
f8f0dec0b2ef: Pull complete
7109f2ab3080: Pull complete
fe1e1dda18a5: Pull complete
Digest: sha256:a1ebc64daa170324dde5b668829de85487575eaa2bdea5216b4c983b1822f9df
Status: Downloaded newer image for ruby:latest
如果我們本地沒有映象,Docker 會自動下載。一旦容器構建過程完成,Docker 將為我們開啟容器。
root@9d057cf9e33d:/#
root@9d057cf9e33d:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin scripts srv sys tmp usr var
root@9d057cf9e33d:/# cd scripts
root@9d057cf9e33d:/scripts# ls
我們可以看到容器中的指令碼目錄是空的。
現在,讓我們轉到主機中的指令碼目錄並在該目錄中建立一個新檔案。它將自動反映在 Docker 容器目錄指令碼中。
isaac@DESKTOP-HV44HT6:~/Desktop$ cd scripts
isaac@DESKTOP-HV44HT6:~/Desktop/scripts$ touch new_file.txt
touch: cannot touch 'new_file.txt': Permission denied
isaac@DESKTOP-HV44HT6:~/Desktop/scripts$ sudo touch new_file.txt
[sudo] password for isaac:
isaac@DESKTOP-HV44HT6:~/Desktop/scripts$ ls
new_file.txt
isaac@DESKTOP-HV44HT6:~/Desktop/scripts$
一旦我們在本地目錄中建立了一個檔案,它將顯示在下面的容器目錄中。
root@913609933be2:/scripts# ls
new_file.txt
使用 --mount
標誌將主機目錄掛載到 Docker 容器中
這是一種比 -v
標籤更直接的方法,由多個鍵值對組成,用逗號分隔。對於這些標籤,欄位的順序無關緊要。
但是,與 -v
標籤相比,它更加冗長。
這些方法由以下命令組成:
- 裝載型別,例如
Bind
、volume
或tmpfs
。 - 源,即我們要掛載的主機上的目錄的路徑,通常用
src
表示。 - 目標,即我們要掛載目錄的容器上目錄的路徑。
- 我們還有其他選項,例如只讀選項和繫結傳播,可以將此目錄指定為私有或共享。
一旦我們記下所有需要的欄位,尤其是源和目標,我們就可以執行如下所示的命令。
在這種情況下,我們使用官方 Nginx 映象來構建容器並將本地目錄名稱 new_scripts
對映到位於 etc/nginx
的目錄。
$ docker run -d \
> -it \
> --mount type=bind,source=$HOME/Desktop/scripts/new_scripts,target=/etc/nginx \
> nginx \
> bash
e079e3254970e290ae68473239e101c6aa8ba4ba56482c75cd21f9bb9f49600b
現在我們成功對映了這兩個目錄,對主機上的目錄所做的任何更改都會自動反映在容器中的目錄上。
isaac@DESKTOP-HV44HT6:~/Desktop/scripts/new_scripts$ sudo touch new_file.txt
[sudo] password for isaac:
isaac@DESKTOP-HV44HT6:~/Desktop/scripts/new_scripts$ ls
new_file.txt
這個檔案會在對映到這個目錄的 docker 目錄中體現出來,說明我們已經成功對映了這兩個目錄。
root@e079e3254970:/etc# cd nginx
root@e079e3254970:/etc/nginx# ls
new_file.txt
まとめ
我們已經成功演示瞭如何使用 Docker -v
和 -mount
標籤掛載目錄。
但是,我們也應該注意,當使用 -v
標籤掛載一個不存在的目錄時,Docker 會自動建立它; 這與使用 Docker --mount
標籤時的情況不同。
在開發新應用程式時,我們應該考慮使用 Docker 卷。
Isaac Tony is a professional software developer and technical writer fascinated by Tech and productivity. He helps large technical organizations communicate their message clearly through writing.
LinkedIn