簡體   English   中英

如何在 Docker 容器中掛載主機目錄

[英]How to mount a host directory in a Docker container

我正在嘗試將主機目錄掛載到 Docker 容器中,以便在主機上完成的任何更新都反映到 Docker 容器中。

我在哪里做錯了什么。 這是我所做的:

kishore$ cat Dockerfile

FROM ubuntu:trusty
RUN apt-get update
RUN apt-get -y install git curl vim
CMD ["/bin/bash"]
WORKDIR /test_container
VOLUME ["/test_container"]

kishore$ tree
.
├── Dockerfile
└── main_folder
    ├── tfile1.txt
    ├── tfile2.txt
    ├── tfile3.txt
    └── tfile4.txt

1 directory, 5 files kishore$ pwd /Users/kishore/tdock

kishore$ docker build --tag=k3_s3:latest .

Uploading context 7.168 kB
Uploading context
Step 0 : FROM ubuntu:trusty
 ---> 99ec81b80c55
Step 1 : RUN apt-get update
 ---> Using cache
 ---> 1c7282005040
Step 2 : RUN apt-get -y install git curl vim
 ---> Using cache
 ---> aed48634e300
Step 3 : CMD ["/bin/bash"]
 ---> Running in d081b576878d
 ---> 65db8df48595
Step 4 : WORKDIR /test_container
 ---> Running in 5b8d2ccd719d
 ---> 250369b30e1f
Step 5 : VOLUME ["/test_container"]
 ---> Running in 72ca332d9809
 ---> 163deb2b1bc5
Successfully built 163deb2b1bc5
Removing intermediate container b8bfcb071441
Removing intermediate container d081b576878d
Removing intermediate container 5b8d2ccd719d
Removing intermediate container 72ca332d9809

kishore$ docker run -d -v /Users/kishore/main_folder:/test_container k3_s3:latest c9f9a7e09c54ee1c2cc966f15c963b4af320b5203b8c46689033c1ab8872a0ea

kishore$ docker run -i -t k3_s3:latest /bin/bash

root@0f17e2313a46:/test_container# ls -al
total 8
drwx------  2 root root 4096 Apr 29 05:15 .
drwxr-xr-x 66 root root 4096 Apr 29 05:15 ..

root@0f17e2313a46:/test_container# exit exit

kishore$ docker -v
Docker version 0.9.1, build 867b2a9

  • 我不知道如何檢查 boot2docker 版本

問題,面臨的問題:

  1. 我如何需要將 main_folder 鏈接到 docker 容器內的 test_container 文件夾?
  2. 我需要自動做到這一點。 在不真正使用run -d -v命令的情況下如何做到這一點?
  3. 如果 boot2docker 崩潰了怎么辦? Docker 文件存儲在哪里(Dockerfile 除外)?

有幾種方法可以做到這一點。 最簡單的方法是使用 dockerfile ADD命令,如下所示:

ADD . /path/inside/docker/container

但是,在構建 dockerfile 后對主機上的此目錄所做的任何更改都不會顯示在容器中。 這是因為在構建容器時,docker 會將目錄壓縮為.tar並將該上下文永久上傳到容器中。

第二種方法是您嘗試的方式,即掛載卷。 由於試圖盡可能便攜,您無法將主機目錄映射到 dockerfile 中的 docker 容器目錄,因為主機目錄可能會根據您運行的機器而改變。 要將主機目錄映射到 docker 容器目錄,您需要在使用docker run時使用-v標志,例如:

# Run a container using the `alpine` image, mount the `/tmp`
# directory from your host into the `/container/directory`
# directory in your container, and run the `ls` command to
# show the contents of that directory.
docker run \
    -v /tmp:/container/directory \
    alpine \
    ls /container/directory

這個問題的用戶使用的是Docker version 0.9.1, build 867b2a9 ,我會給你一個 docker version >= 17.06 的答案。

你想要的,在容器目錄中保持本地目錄同步,是通過使用bind類型掛載卷來完成的。 這將綁定源(您的系統)和目標(在 docker 容器中)目錄。 這幾乎與在linux上掛載目錄相同。

根據 Docker 文檔,掛載的適當命令現在是mount而不是-v 這是它的文檔:

  • --mount :由多個鍵值對組成,以逗號分隔。 每個鍵/值對都采用<key>=<value>元組的形式。 --mount語法比-v--volume更冗長,但鍵的順序並不重要,標志的值更容易理解。

  • 掛載type ,可以是bindvolumetmpfs (我們將使用bind

  • 坐騎的source 對於綁定掛載,這是 Docker 守護程序主機上文件或目錄的路徑。 可以指定為sourcesrc

  • destination將文件或目錄安裝在容器中的路徑作為其值。 可以指定為destinationdsttarget

因此,要使用/test_container (目標)掛載當前目錄(源),我們將使用:

    docker run -it --mount src="$(pwd)",target=/test_container,type=bind k3_s3

如果這些掛載參數有空格,您必須在它們周圍加上引號。 當我知道他們不知道時,我會使用`pwd`代替:

    docker run -it --mount src=`pwd`,target=/test_container,type=bind k3_s3

您還必須處理文件權限,請參閱這篇文章

您可以使用 cli 中的 -v 選項,此功能無法通過 Dockerfile 獲得

docker run -t -i -v <host_dir>:<container_dir> ubuntu /bin/bash

其中 host_dir 是您要掛載的主機目錄。 如果容器目錄不存在,您無需擔心容器目錄,docker 會創建它。

如果您從主機(在 root 權限下)對 host_dir 進行任何更改,它將對容器可見,反之亦然。

2 次連續掛載:我猜這里的許多帖子可能使用了兩個 boot2docker,您看不到任何內容的原因是您正在從 boot2docker 掛載一個目錄,而不是從您的主機上掛載。

你基本上需要2個連續的坐騎:

第一個將目錄從主機掛載到系統的

第二個將新目錄從 boot2docker 掛載到你的容器,如下所示:

  • 1)在boot2docker上掛載本地系統

    sudo mount -t vboxsf hostfolder /boot2dockerfolder
  • 2)在linux容器上掛載boot2docker文件

    docker run -v /boot2dockerfolder:/root/containerfolder -i -t imagename

然后,當您lscontainerfolder時,您將看到hostfolder的內容。

您是否可以通過boot2docker或類似的方式在 OS X 上使用 docker。

我也有同樣的經歷——命令是正確的,但無論如何都沒有(明智的)安裝在容器中。

事實證明 - 它已經在docker 文檔中進行了解釋。 當您鍵入docker run -v /var/logs/on/host:/var/logs/in/container .../var/logs/on/host實際上是從boot2docker虛擬機映像映射的,而不是您的 Mac。

您必須通過 VM 將共享文件夾通過管道傳輸到您的實際主機(在我的情況下為 Mac)。

我只是在嘗試讓我的 SailsJS 應用程序在 Docker 容器內運行,以保持我的物理機器清潔。

我正在使用以下命令在 /app 下安裝 SailsJS/NodeJS 應用程序:

cd my_source_code_folder
docker run -it -p 1337:1337 -v $(pwd):/app my_docker/image_with_nodejs_etc

[更新]截至 2017 年 6 月, Docker for Mac負責處理所有煩人的部分,您必須使用 VirtualBox。 它允許您使用/private前綴基本上映射本地主機上的所有內容。 更多信息在這里 [/更新]

當前所有答案都在談論 Boot2docker。 由於現在不贊成使用 docker-machine,因此這適用於 docker-machine:

首先,通過 ssh 進入 docker-machine vm 並創建我們將映射到的文件夾:

docker-machine ssh $MACHINE_NAME "sudo mkdir -p \"$VOL_DIR\""

現在將文件夾共享到 VirtualBox:

WORKDIR=$(basename "$VOL_DIR")
vboxmanage sharedfolder add "$MACHINE_NAME" --name "$WORKDIR" --hostpath "$VOL_DIR" --transient

最后,再次 ssh 進入 docker-machine 並掛載我們剛剛共享的文件夾:

docker-machine ssh $MACHINE_NAME "sudo mount -t vboxsf -o uid=\"$U\",gid=\"$G\" \"$WORKDIR\" \"$VOL_DIR\""

注意:對於 UID 和 GID,您基本上可以使用任何整數,只要它們還沒有被占用。

這是從 OS X El Capitan 上的 docker-machine 0.4.1 和 docker 1.8.3 開始測試的。

docker run -v /host/directory:/container/directory -t IMAGE-NAME /bin/bash

docker run -v /root/shareData:/home/shareData -t kylemanna/openvpn /bin/bash

在我的系統中,我已經更正了 nhjk 的答案,當您添加-t標志時它可以完美運行。

在 Mac OS 上,要將文件夾/Users/<name>/projects/掛載到您的 mac 上容器的根目錄:

docker run -it -v /Users/<name>/projects/:/projects <container_name> bash

ls /projects

使用command-line

docker run -it --name <WHATEVER> -p <LOCAL_PORT>:<CONTAINER_PORT> -v <LOCAL_PATH>:<CONTAINER_PATH> -d <IMAGE>:<TAG>

使用docker-compose.yaml

version: '2'
  services:
    cms:
       image: <IMAGE>:<TAG>
       ports:
       - <LOCAL_PORT>:<CONTAINER_PORT>
       volumes:
       - <LOCAL_PATH>:<CONTAINER_PATH>

認為 :

  • 圖片:k3_s3
  • 標簽: 最新
  • 本地端口:8080
  • 容器端口:8080
  • LOCAL_PATH: /volume-to-mount
  • CONTAINER_PATH: /mnt

例子 :

  1. 首先創建 /volume-to-mount。 (如果有則跳過)
$ mkdir -p /volume-to-mount
  1. docker-compose -f docker-compose.yaml up -d
version: '2'
  services:
    cms:
       image: ghost-cms:latest
       ports:
       - 8080:8080
       volumes:
       - /volume-to-mount:/mnt
  1. 驗證您的容器:
docker exec -it CONTAINER_ID ls -la /mnt

對於那些想要在當前目錄中掛載文件夾的人:

docker run -d --name some-container -v ${PWD}/folder:/var/folder ubuntu

如果主機是 Windows 10,則不要使用正斜杠,而是使用反斜杠 -

docker run -it -p 12001:80 -v c:\Users\C\Desktop\dockerStorage:/root/sketches

確保主驅動器是共享的(在本例中為 C)。 就我而言,在運行上面的命令后,我收到了詢問共享權限的提示。

對於Windows 10用戶,將掛載點放在C:/Users/目錄中很重要。 我嘗試了幾個小時來讓它工作。 這篇文章有所幫助,但起初並不明顯,因為 Windows 10 的解決方案是對已接受答案的評論。 我是這樣做的:

docker run -it -p 12001:80 -v //c/Users/C/Desktop/dockerStorage:/root/sketches \
<your-image-here> /bin/bash

然后要對其進行測試,您可以在圖像中執行echo TEST > hostTest.txt 您應該能夠在C:/Users/C/Desktop/dockerStorage/的本地主機文件夾中看到這個新文件。

2015 年 7 月更新 - boot2docker 現在支持直接掛載。 您可以直接在 Mac 提示符下使用-v /var/logs/on/host:/var/logs/in/container ,無需雙重掛載

從 Docker 18-CE 開始,您可以使用docker run -v /src/path:/container/path對主機文件夾進行雙向綁定。

但是,如果您使用的是 Windows 10/WSL,並且將 Docker-CE for Windows 作為您的主機,然后在 WSL 中使用 docker-ce 客戶端工具,那么這里有一個主要問題。 WSL 知道整個 / 文件系統,而您的 Windows 主機只知道您的驅動器。 在 WSL 中,您可以使用 /mnt/c/projectpath,但是如果您嘗試 docker docker run -v ${PWD}:/projectpath ,您會在主機中發現 /projectpath/ 為空,因為在主機上 /mnt 沒有任何意義.

如果您從 /c/projectpath 工作,然后執行 docker docker run -v ${PWD}:/projectpath ,您將在容器中找到它,/projectpath 將實時反映 /c/projectpath 。 除了在您的客人中看到空掛載之外,沒有任何錯誤或任何其他方法可以檢測此問題。

您還必須確保在 Docker for Windows 設置中“共享驅動器”。

我一直有同樣的問題。 我的命令行如下所示:

docker run --rm -i --name $NAME -v `pwd`:/sources:z $NAME

問題出在“密碼”上。 所以我把它改成了 $(pwd):

docker run --rm -i --name $NAME -v $(pwd):/sources:z $NAME

如何將 main_folder 鏈接到 docker 容器內的 test_container 文件夾?

您下面的命令是正確的,除非您在使用 boot2docker 的 Mac 上(取決於將來的更新),在這種情況下您可能會發現文件夾為空。 有關更正此問題的教程,請參閱 mattes answer。

docker run -d -v /Users/kishore/main_folder:/test_container k3_s3:latest

我需要讓它自動運行,如何在不真正使用 run -d -v 命令的情況下做到這一點。

您無法真正擺脫使用這些命令,它們是 docker 工作方式所固有的。 您最好將它們放入 shell 腳本中,以免重復寫出它們。

如果 boot2docker 崩潰了怎么辦? docker 文件存儲在哪里?

如果您設法使用 -v 參數並引用您的主機,那么文件在您的主機上將是安全的。

如果您使用過“docker build -t myimage”。 使用 Dockerfile,您的文件將被烘焙到圖像中。

我相信您的 docker 映像存儲在 boot2docker-vm 中。 當我從 VirtualBox 中刪除 vm 時,我的圖像消失了,我發現了這一點。 (注意,我不知道 Virtualbox 是如何工作的,所以圖像可能仍然隱藏在其他地方,只是對 docker 不可見)。

有同樣的問題。 docker 文檔中找到了這個:

注意:主機目錄本質上是依賴於主機的。 出於這個原因,您不能從 Dockerfile 掛載主機目錄,VOLUME 指令不支持傳遞主機目錄,因為構建的圖像應該是可移植的。 主機目錄不會在所有潛在主機上都可用。

因此,只能使用docker run命令中的-v參數安裝讀/寫主機目錄,因為其他答案正確指出。

我發現任何位於系統指令(如/var/usr/etc )下的目錄都無法掛載在容器下。

該指令應該在用戶空間-v開關指示 docker daemon 將本地目錄掛載到容器,例如:

docker run -t -d -v /{local}/{path}:/{container}/{path} --name {container_name} {imagename}

這是一個帶有 Windows 路徑的示例:

docker run -P -it --name organizr --mount src="/c/Users/MyUserName/AppData/Roaming/DockerConfigs/Organizr",dst=/config,type=bind organizrtools/organizr-v2:latest

作為旁注,在所有這些頭發拉扯過程中,不得不努力弄清楚,一遍又一遍地重新輸入路徑,我決定編寫一個小的AutoHotkey腳本來將 Windows 路徑轉換為“Docker Windows ”格式小路。 這樣,我所要做的就是將任何我想用作掛載點的 Windows 路徑復制到剪貼板,按鍵盤上的“應用程序鍵”,它會將其格式化為 Docker 欣賞的路徑格式。

例如:

將此復制到剪貼板:

C:\Users\My PC\AppData\Roaming\DockerConfigs\Organizr

當光標位於命令行上您想要的位置時按Apps Key ,它會將其粘貼到那里:

"/c/Users/My PC/AppData/Roaming/DockerConfigs/Organizr"

為我節省了很多時間。 在這里,它適用於任何可能覺得它有用的人。

; --------------------------------------------------------------------------------------------------------------
;
; Docker Utility: Convert a Windows Formatted Path to a Docker Formatter Path
;                   Useful for (example) when mounting Windows volumes via the command-line.
;
; By:       J. Scott Elblein
; Version:  1.0
; Date:     2/5/2019
;
; Usage:    Cut or Copy the Windows formatted path to the clipboard, press the AppsKey on your keyboard
;           (usually right next to the Windows Key), it'll format it into a 'docker path' and enter it
;           into the active window. Easy example usage would be to copy your intended volume path via
;           Explorer, place the cursor after the "-v" in your Docker command, press the Apps Key and
;           then it'll place the formatted path onto the line for you.
;
; TODO::    I may or may not add anything to this depending on needs. Some ideas are:
;           
;           - Add a tray menu with the ability to do some things, like just replace the unformatted path
;               on the clipboard with the formatted one rather than enter it automatically.
;           - Add 'smarter' handling so the it first confirms that the clipboard text is even a path in
;               the first place. (would need to be able to handle Win + Mac + Linux)
;           - Add command-line handling so the script doesn't need to always be in the tray, you could
;               just pass the Windows path to the script, have it format it, then paste and close.
;               Also, could have it just check for a path on the clipboard upon script startup, if found
;               do it's job, then exit the script.
;           - Add an 'all-in-one' action, to copy the selected Windows path, and then output the result.
;           - Whatever else comes to mind.
;
; --------------------------------------------------------------------------------------------------------------

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%

AppsKey::

    ; Create a new var, store the current clipboard contents (should be a Windows path)
    NewStr := Clipboard

    ; Rip out the first 2 chars (should be a drive letter and colon) & convert the letter to lowercase
    ; NOTE: I could probably replace the following 3 lines with a regexreplace, but atm I'm lazy and in a rush.
    tmpVar := SubStr(NewStr, 1, 2)
    StringLower, tmpVar, tmpVar

    ; Replace the uppercase drive letter and colon with the lowercase drive letter and colon
    NewStr := StrReplace(NewStr, SubStr(NewStr, 1, 2), tmpVar)

    ; Replace backslashes with forward slashes
    NewStr := StrReplace(NewStr,  "\", "/")

    ; Replace all colons with nothing
    NewStr := StrReplace(NewStr, ":", "")

    ; Remove the last char if it's a trailing forward slash
    NewStr :=  RegExReplace(NewStr, "/$")

    ; Append a leading forward slash if not already there
    if RegExMatch(NewStr, "^/") == 0
        NewStr :=  "/" . NewStr

    ; If there are any spaces in the path ... wrap in double quotes
    if RegExMatch(NewStr, " ") > 0
        NewStr :=  """" . NewStr . """"

    ; Send the result to the active window
    SendInput % NewStr 

為了讓它在Windows 10中運行,我必須從系統托盤打開 Docker 設置窗口並轉到共享驅動器部分。

然后我選中了C旁邊的框。 Docker 要求我提供桌面憑據以獲得寫入我的用戶文件夾的授權。

然后我按照上面的示例以及該設置頁面上的示例運行 docker 容器,附加到容器中的/data

docker run -v c:/Users/<user.name>/Desktop/dockerStorage:/data -other -options

boot2docker 和 VirtualBox 來賓添加
如何將 /Users 掛載到 boot2docker

https://medium.com/boot2docker-lightweight-linux-for-docker/boot2docker-together-with-virtualbox-guest-additions-da1e3ab2465c

tl;dr 使用 VirtualBox Guest Additions 構建您自己的自定義 boot2docker.iso(請參閱鏈接)或下載http://static.dockerfiles.io/boot2docker-v1.0.1-virtualbox-guest-additions-v4.3.12.iso並保存到 ~/.boot2docker/boot2docker.iso。

請注意,在 Windows 中,您必須提供絕對路徑。

下面為我​​工作。

docker run -t -i -v D:/projects/:/home/chankeypathak/work -p 8888:8888 jupyter/tensorflow-notebook /bin/bash

我有同樣的問題,我試圖在 docker 上掛載 C:\Users\ 文件夾
我就是這樣做的 Docker Toolbox 命令行

 $ docker run -it --name <containername> -v /c/Users:/myVolData <imagename>

您也可以使用Portainer Web 應用程序執行此操作,以獲得不同的視覺體驗。

首先拉取 Portainer 鏡像:

docker pull portainer/portainer

然后為 Portainer 創建一個卷:

docker volume create portainer_data

同時創建一個 Portainer 容器:

docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

您將能夠使用瀏覽器通過以下 URL 訪問 Web 應用程序:“ http://localhost:9000 ”。 首次登錄時,系統會提示您設置 Portainer 管理員憑據。

在 Web 應用程序中,按照以下菜單和按鈕操作:(容器 > 添加容器 >填充設置> 部署容器)

我在使用 Portainer 創建“掛載”卷時遇到了麻煩,我意識到在創建容器卷時我必須單擊“綁定”。 下面是卷綁定設置的圖示,該設置適用於我的容器創建,其中已安裝卷綁定到主機。

卷綁定設置

PS:我使用的是 Docker 19.035 和 Portainer 1.23.1

我有從容器掛載主機目錄的相同要求,我使用了卷掛載命令。 但是在測試過程中注意到它也在容器內創建文件但是經過一些挖掘發現它們只是符號鏈接和實際使用的文件系統來自主機。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM