我正在嘗試將主機目錄綁定到容器內的某個目錄,並期望容器內所做的更改應該反映在主機上。
這是我遵循的步驟
在主機上建立 /hostdir 並以特權模式執行 ubuntu 容器
[root@nhbdlin03 ~]# mkdir /hostdir
[root@nhbdlin03 ~]# docker run -itd --privileged --name ubuntu -v /hostdir:/hostdir:z ubuntu
76aebded33274e95a6f569d0831aee4df27e9f200a8fd0401448239bd6f5bf80
[root@nhbdlin03 ~]# docker exec -it ubuntu bash
在容器內建立一個container_dir
root@76aebded3327:/# mkdir /container_dir
綁定兩個目錄(成功)
root@76aebded3327:/# mount --bind /container_dir /hostdir
在 /container_dir 中建立一個名為 hello.txt 的文件
root@76aebded3327:/# cd container_dir/
root@76aebded3327:/container_dir# touch hello.txt
它會反映在 /hostdir 內,因為它綁定安裝到 /container_dir
root@76aebded3327:/container_dir# ls /hostdir/
hello.txt
退出容器並檢查主機,反映是相同的
root@76aebded3327:/container_dir# exit
[root@nhbdlin03 ~]# ls /hostdir/
[root@nhbdlin03 ~]# ls /hostdir/ | wc -l
0
[root@nhbdlin03 ~]#
內容沒有被反映。
我錯過了一些東西或做完全錯誤的事情,請幫助我朝著正確的方向前進。
答案1
這是設計使然——出於多種原因,在容器內完成的安裝在外部是不可見的。
容器運行在單獨的掛載命名空間(不僅僅是簡單的 chroot)中,Docker 很可能以「私有」模式配置新的命名空間,部分是為了防止容器的各種掛載混亂主機的findmnt
,部分是為了更容易反組譯當容器退出時,所有內容都會掛載。
(當所有掛載僅從命名空間內部可見時,就足以殺死所有進程 - 然後掛載將被核心自動拆除。但如果其中一些掛載在外部可見,則「主機作業系統」進程可能會保留它們「正在使用」。
您可能需要mount --make-[r]shared /
在正確的時間進行類似的操作,以使內部安裝在外部可見。我現在沒有更準確的答案。
您可以使用unshare
和nsenter
工具來試驗名稱空間,而無需涉及 Docker - 例如,unshare --mount --propagation=private
在一個終端中運行,安裝某些東西,然後運行findmnt
以查看它報告“取消共享”進程“內部”和“外部”的不同結果。
答案2
對我有用的是進行 Docker 綁定安裝,shared
如中所述這個答案類似的問題「如何向主機公開容器的掛載點?」:
-v /hostdir:/hostdir:shared
根據Docker 的文檔假設您的主機作業系統使用 SELinux,該z
選項應該實現類似的效果,但我沒有嘗試。