[英]Single file volume mounted as directory in Docker
Docker 文檔說可以將單個文件掛載到 Docker 容器中:
-v 標志還可用於從主機掛載單個文件 - 而不僅僅是目錄。
$ docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash
這將使您進入新容器中的 bash shell,您將擁有來自主機的 bash 歷史記錄,當您退出容器時,主機將擁有在容器中鍵入的命令的歷史記錄。
但是,當我嘗試該文件時,該文件會掛載為目錄:
tom@u ~/project $ docker run --rm -it -v file.json:/file.json test
total 80K
drwxr-xr-x 9 root root 4.0K Dec 7 12:58 .
drwxr-xr-x 63 root root 4.0K Dec 7 12:58 ..
drwxr-xr-x 2 root root 4.0K Dec 4 16:10 file.json
我的 Dockerfile 看起來像這樣:
FROM ubuntu:14.04
MAINTAINER Tom
CMD ["ls", "-lah", "/test"]
Docker 版本為 1.9.1,構建 a34a1d5。
這是文檔問題,是我的誤解,還是還有其他問題?
也許在上面的答案中很清楚......但我花了一些時間才弄清楚我的情況。
導致使用 -v 共享的文件顯示為目錄而不是文件的根本原因是 Docker 在主機上找不到該文件。 因此 Docker 在容器中創建一個新目錄,名稱是主機上不存在的文件的名稱,因為 docker 認為用戶只是想共享一個將來會創建的卷/目錄。
所以在上面報告的問題中,如果你在 -v 命令中使用了相對目錄,而 docker 不理解相對目錄,那意味着在主機上找不到該文件,因此 docker 創建了一個目錄。 當問題是由於相對目錄時,上面建議使用 $(pwd) 的答案將是正確的解決方案。
但是對於那些閱讀此頁面的人來說,他們沒有使用相對目錄並且遇到同樣的問題......然后嘗試了解為什么主機上缺少文件。
這可能只是一個愚蠢的錯字......
可能是您正在從客戶端運行“docker run”命令,該命令在不同的主機上生成 docker 容器,並且正在共享的文件在該不同的主機上不存在。 與 -v 共享的文件必須存在於 docker 代理將生成容器的主機上......不一定在執行“docker run -v ...”命令的客戶端上(盡管它們在許多情況)。
對於 Mac 和 Windows,上面還有其他可能的解釋……也可能是這樣。
因此,主機中丟失的文件是問題所在……解決設置中的問題……使用 $(pwd) 可能是解決方案,但並非總是如此。
test
是您使用“ docker build -t test
” docker build -t test
圖像的名稱,而不是/test
文件夾。
嘗試使用Dockerfile
:
CMD ["ls", "-lah", "/"]
or
CMD ["cat", "/file.json"]
和:
docker run --rm -it -v $(pwd)/file.json:/file.json test
請注意使用$(pwd)
以安裝具有完整絕對路徑的文件(不支持相對路徑)
通過使用$(pwd)
,您將獲得一個確實存在的絕對路徑,並尊重大小寫,而不是可能不存在的文件名或路徑。
不存在的主機路徑將作為文件夾安裝在容器中。
我花了一些時間來解決和診斷在 Windows 上運行 docker 的這個問題。 這也可能影響在 Mac OSX 上運行的人,因此我在此處為可能在這些環境中遇到問題的人添加了一個答案,因為我的搜索將我帶到了這個地方,並添加了對 docker 中似乎發生的事情的解釋。
在 Windows 或 Mac OSX 中,您的 docker 實際上是在 boot2docker VM 中運行的,並且默認情況下實際上只有用戶目錄是共享的。 在 Windows 上,這個用戶目錄被共享為 /c/Users/,但是在 Docker Machine 附帶的 MinGW shell 中,驅動器可以作為 /C 或 /c 訪問,所以如果你忘記了 docker 命令,這會讓你抓狂實際上針對 boot2docker VM 運行,並且您的文件路徑必須存在於 boot2docker VM 上,並以它們在那里存在的方式指定,因為 docker 中似乎發生的是,而不是給出目錄/文件所做的警告或錯誤不存在,docker 會在 boot2docker VM 中靜默創建指定的源作為目錄,因此沒有准備好的輸出表明您正在做任何不正確的事情。
因此,與上面的答案一樣,如果您的文件安裝為目錄,請檢查您是否提供了絕對路徑。 對於 Windows 和 Mac OSX,請檢查您安裝的絕對路徑是否存在於您的 boot2docker VM 中。
在 docker 中運行 docker 時(例如通過掛載/var/run/docker.sock
),您需要注意,如果您在 docker 中掛載,則使用的文件路徑始終是您主機上的文件路徑。
因此,如果在您的主機上執行以下掛載:
-v /tmp/foobar.txt:/my/path/foobar.txt
你不應該做以下安裝內泊塢窗:
-v /my/path/foobar.txt:/my/other/path.txt
而是使用主機文件路徑,例如:
-v /tmp/foobar.txt:/my/other/path.txt
正如 edi9999 指出的那樣,如果你告訴 docker 守護進程掛載一個文件,它不會查看你當前容器的文件系統,它會查看運行守護進程的文件系統。
如果您的 docker 守護程序出於某種原因在其他地方運行,您可能會遇到此問題。
❯ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock docker
/ # echo "bar" > /foo
/ # docker run --rm -v /foo:/foo ubuntu bash -c 'cat foo'
cat: foo: Is a directory
Docker 在它的主機上找不到 /foo 文件,所以它(有用?)在那里創建一個目錄,所以至少你已經安裝了一些東西。
您可以通過將主機目錄安裝到外部容器中,然后將該目錄用於要出現在內部容器中的卷來解決此問題:
❯ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock -v /dev/shm:/dev/shm docker
/ # echo "bar" > /dev/shm/foo
/ # docker run --rm -v /dev/shm/foo:/dev/shm/foo ubuntu bash -c 'cat /dev/shm/foo'
bar
這使得路徑/dev/shm/foo
在任一上下文中都引用同一個文件,因此您可以從外部容器引用該文件,守護進程將在主機上找到它,這意味着它將在內部容器,而不是目錄。
對於那些使用 VirtualBox 機器的人來說,有一個簡單的解決方案。 默認情況下,添加 C:/User 文件夾。 如果您的項目在 C:/projects 中,請添加此文件夾以使其在 VB 中可用(使用自動掛載)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.