如何将卷添加到现有Docker容器?

mah*_*nya 243 docker

我有一个Docker容器,我只是通过在Ubuntu上安装Docker并创建:

sudo docker run -i -t ubuntu /bin/bash
Run Code Online (Sandbox Code Playgroud)

我立即开始安装Java和其他一些工具,花一些时间用它来停止容器

exit
Run Code Online (Sandbox Code Playgroud)

然后我想添加一个卷,并意识到这并不像我想象的那么简单.如果我使用sudo docker -v /somedir run ...那么我最终得到一个新的容器,所以我已经安装了Java并且做了我之前已经完成的工作,只是为了到达一个装有卷的容器.

有关从主机安装文件夹的所有文档似乎都暗示在创建容器时可以安装卷.因此,我必须避免从头开始重新配置新容器的唯一选择是将现有容器提交到存储库,并在安装卷时将其用作新容器的基础.

这确实是向现有容器添加卷的唯一方法吗?

Leo*_*ejo 317

您可以提交现有容器(即从容器的更改创建新映像),然后使用新安装运行它.

例:

$ docker ps  -a
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS                          PORTS               NAMES
    5a8f89adeead        ubuntu:14.04          "/bin/bash"              About a minute ago   Exited (0) About a minute ago                       agitated_newton

$ docker commit 5a8f89adeead newimagename

$ docker run -ti -v "$PWD/dir1":/dir1 -v "$PWD/dir2":/dir2 newimagename /bin/bash
Run Code Online (Sandbox Code Playgroud)

如果一切正常,请停止旧容器,并使用这个新容器.

而已 :)

  • 如果由于某种原因需要新容器取旧名称,请在删除旧容器后使用[docker rename](https://docs.docker.com/engine/reference/commandline/rename/). (14认同)
  • 只是想指出上面你提到`newnameofcontainer`这应该命名为`new_image_name` - 因为`docker commit`在你的系统上创建了一个新的*image*.然后在下面执行`docker run`时,实际上使用了要从中运行新容器的*image*的名称.上面的工作,但只是想让其他人澄清上面的占位符newnameofcontainer实际上是新图像的名称.谢谢!很棒的答案.哦,你可以使用`docker image ls`从第一个docker commit命令中看到新创建的图像 (9认同)
  • 这不会保留在原始容器中运行的进程。 (7认同)
  • 提交容器不会保留卷绑定,有什么解决方案吗? (4认同)
  • 实际上,如果要从图像开始,则不需要提交新容器.只是`docker run -v/srv/a:/ tmp ubuntu:14.04`很好. (3认同)

use*_*364 67

我们没有办法在运行容器中添加卷,但为了达到这个目的,您可以使用以下命令:

在容器和本地文件系统之间复制文件/文件夹: -

docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
Run Code Online (Sandbox Code Playgroud)

供参考:

https://docs.docker.com/engine/reference/commandline/cp/

  • 安装卷和从容器复制文件之间存在巨大差异...... (31认同)
  • 无论如何它帮助了我.我不知道'docker cp'命令,并试图实现这一点 - 将文件从运行容器复制到主机. (24认同)
  • 这确实不完全是OP的情况,但我来这里寻找一种将卷附加到*正在运行的*容器的方法。我的目标是在容器运行时动态地将一些内容放入/取出容器;假设我不控制容器的创建,并且没有停止它的选项。这个答案实际上指出了实现这一目标的唯一方法。所以,+1,谢谢! (11认同)
  • 我不明白为什么有这么多票,这对于所提出的问题来说是一个非常错误的答案。 (6认同)
  • 高度误导,不应有太多的投票。 (3认同)
  • 它不是坐骑,但在容器和本地主机之间方便地带回文件很方便。 (2认同)
  • 虽然这确实解决了本地复制容器内容的问题,但这并不等同于安装卷,因此不应被视为替代方案。也就是说,复制必须由用户管理,并且数据现在存在于两个地方。 (2认同)
  • 如前所述,不支持在运行容器中添加卷,我认为这是最接近的答案。在我们的例子中,我们不想再次复制 apache htdocs 和 mysql 数据库设置过程,步骤:1) 创建一个包含所需卷的新重复容器 2) 将相关文件夹复制到新容器 3) 删除旧容器 -f (2认同)

Igo*_*rup 15

我已成功将/home/<user-name>主机的/mnt文件夹安装到现有(未运行)容器的文件夹中。您可以通过以下方式进行操作:

  1. 打开与停止的容器相对应的配置文件,该文件可以在上找到/var/lib/docker/containers/99d...1fb/config.v2.json(可能config.json适用于旧版本的docker)。

  2. 查找MountPoints部分,在我的情况下为空:"MountPoints":{}。接下来,将内容替换为类似的内容(您可以使用正确的设置从另一个容器复制正确的内容):

    "MountPoints":{"/mnt":{"Source":"/home/<user-name>","Destination":"/mnt","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/home/<user-name>","Target":"/mnt"},"SkipMountpointCreation":false}}

    或相同(格式):

  "MountPoints": {
    "/mnt": {
      "Source": "/home/<user-name>",
      "Destination": "/mnt",
      "RW": true,
      "Name": "",
      "Driver": "",
      "Type": "bind",
      "Propagation": "rprivate",
      "Spec": {
        "Type": "bind",
        "Source": "/home/<user-name>",
        "Target": "/mnt"
      },
      "SkipMountpointCreation": false
    }
  }
Run Code Online (Sandbox Code Playgroud)
  1. 重新启动docker服务: service docker restart

这对我适用于Ubuntu 18.04.1和Docker 18.09.0

  • **关键一步**是`service docker restart`。我尝试“docker restart &lt;container&gt;”,然后新配置没有被拾取,并且它被旧配置覆盖。 (7认同)
  • 这是最好的答案,因为它可以完全保留现有容器。这就是我所做的:1.停止docker引擎:`systemctl stop docker.service` 2.编辑`config.v2.json`:`vim &lt;(jq。/ var / lib / docker / containers / &lt;container-ID &gt; /config.v2.json)`3.将更新保存到文件:`:w config.v2.json` 4.退出vim:`:q!`5.更新现有文件:`jq -c。config.v2.json&gt; / var / lib / docker / containers / &lt;container-ID&gt; / config.v2.json` 6.启动docker引擎:`systemctl start docker.service` 7.必要时启动容器:` docker start &lt;容器名称/ ID&gt;`8.享受:-) (3认同)
  • 感谢您的回答。第三步至关重要。我还要补充一点,最好是在执行写入操作之前先停止docker容器。 (2认同)
  • 看来我在 Docker 版本 20.10.7 中无法通过容器 id 找到 `config.v2.json` (2认同)

R0M*_*RMY 12

JérômePetazzoni有一篇非常有趣的博客文章,介绍如何在容器运行时将卷附加到容器中.这不是开箱即用的Docker内置的东西,但可以实现.

正如他也指出的那样

这不适用于不基于块设备的文件系统.

它只有在/ proc/mounts正确列出块设备节点时才会起作用(正如我们上面所看到的那样,它不一定是真的).

另外,我只在我当地的环境中测试过这个; 我甚至没有试过云实例或类似的东西

因人而异


Ade*_*lal 7

不幸的是,只能在run命令中找到安装卷的switch选项.

docker run --help

-v, --volume list Bind mount a volume (default [])

有一种方法可以解决这个问题,因此您不必重新安装已经在容器上设置的应用程序.

  1. 导出容器 docker container export -o ./myimage.docker mycontainer
  2. 导入为图像 docker import ./myimage.docker myimage
  3. 然后 docker run -i -t -v /somedir --name mycontainer myimage /bin/bash


dro*_*ebi 6

找这个问题找了半天后使用Docker Windows容器的一个注意事项!

条件:

  • 视窗 10
  • Docker 桌面(最新版本)
  • 将 Docker Windows 容器用于映像 microsoft/mssql-server-windows-developer

问题:

  • 我想将主机字典安装到我的 Windows 容器中。

此处部分描述的解决方案:

  • 创建 docker 容器

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer

  • 转到容器中的命令外壳

docker exec -it <CONTAINERID> cmd.exe

  • 创建目录

mkdir DirForMount

  • 停止容器

docker container stop <CONTAINERID>

  • 提交容器

docker commit <CONTAINERID> <NEWIMAGENAME>

  • 删除旧容器

docker container rm <CONTAINERID>

  • 创建具有新图像和卷挂载的新容器

docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y -v C:\DirToMount:C:\DirForMount <NEWIMAGENAME>

在此之后,我在 docker windows 容器上解决了这个问题。