Docker如何将文件从容器复制到主机?

时间:2020-06-22 16:17:13

标签: node.js docker

我面临着使用容器共享主机上文件夹中数据的需求。应当在主机上读取或修改在容器内部创建的数据,反之亦然。

我决定为此使用Docker Run -v arg。 我受到这个项目的启发。 https://github.com/itzg/docker-minecraft-server。我对您描述的原理也在那里实现。

docker run -d -v /path/on/host:/data \
    -e TYPE=PAPER -e FORCE_REDOWNLOAD=true \
    -p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server

所有数据将在/path/on/host中的主机上可用。可以在主机上修改文件,所有更改都将转移到容器中,反之亦然。 /path/on/host/data文件夹会不断链接。

因此,我决定在我的项目中执行此操作-一个nodejs机器人。但是没有结果,因为文件不会从容器复制到主机。只能从主机访问容器访问文件。现在,我想知道如何将文件从容器复制到主机。

如何与上面的示例相同或如何以不同的方式实现它,以方便地在一行中从终端启动共享文件夹中的实例?

其他指南对我没有帮助。我想与-v一起使用。


将在WORKDIR中创建文件

docker run --name app node-app

WORKDIR将为空或包含/ tmp / node-app中的任何文件

docker run -v /tmp/node-app:/app --name app node-app

Dockerfile

FROM node:lts
VOLUME /app/
COPY ./repo/package.json /app/package.json
WORKDIR /app/
RUN npm install --production
COPY ./repo /app/
CMD npm start

4 个答案:

答案 0 :(得分:0)

rsync是在系统之间共享文件的绝佳方法。在您的内部Docker网络中找到机器的IP地址,然后

rsync -rav <src-directory> <username>@<dest-ip>:<dest-directory> -o

答案 1 :(得分:0)

几个潜在的问题:

  1. 如果您使用的是docker桌面,则必须确保共享目录,因为docker引擎实际上是在VM上运行的,/ tmp可能不等于计算机上的/ tmp。

On macOS: Docker -> Preferences -> Resources -> FILE SHARING

  1. 您还需要小心安装。当您使用上面的“ -v”选项运行容器时,它将在容器内部绑定安装主机目录。如果将目录绑定绑定到“ / app”目录的顶部,则绑定绑定之前将看不到/ app中的内容。您应该选择一个空目录或不存在目录来执行绑定安装。

  2. 当您在Dockerfile中运行“ COPY”时,即从构建上下文中永久且静态地在容器内部复制资产。如果您需要动态资产,请跳过该步骤,然后在运行时进行绑定安装。

答案 2 :(得分:0)

选项1:如果无法更改映像,则可以使用命名卷进行绑定安装。这将为您提供通常在命名卷中看到的常规初始化功能,但会提供您选择的路径。请注意,只有在命名卷为空时才对其进行初始化,一旦命名卷中存在文件,以后的容器启动将不会从容器文件系统复制(例如,如果映像已更新)。这里有3种不同的方式可以完成:

  # create the volume in advance
  $ docker volume create --driver local \
      --opt type=none \
      --opt device=/home/user/test \
      --opt o=bind \
      test_vol

  # create on the fly with --mount
  $ docker run -it --rm \
    --mount type=volume,dst=/container/path,volume-driver=local,volume-opt=type=none,volume-opt=o=bind,volume-opt=device=/home/user/test \
    foo

  # inside a docker-compose file
  ...
  volumes:
    bind-test:
      driver: local
      driver_opts:
        type: none
        o: bind
        device: /home/user/test
  ...

选项2:如果要在多个主机上易于使用,可以在映像中配置一个入口点,以将文件从容器路径复制到卷中。为此,您需要将文件存储在映像中与卷装载不同的位置,然后包括一个运行复制,rsync或类似操作的脚本。我的base image reposave-volumeload-volume脚本中就是一个例子。其他在docker hub上使用主机卷的映像中也使用了类似的技术,特别是我在考虑jenkins映像。

答案 3 :(得分:0)

这可能不是最好的解决方案,但我仍然按照自己的意愿做。事实证明,我只是从表面上了解docker的工作原理。为了更专业地使用docker,我将考虑以上所有评论。谢谢你离开他们。

最终,我添加了ENTRYPOINT指令来运行一个Shell脚本,该脚本无需覆盖就可以复制文件,并通过npm运行该程序。

Dockerfile

FROM node:12-alpine

VOLUME ["/data"]

...

# Copy script
COPY start.sh /home/docker-start.sh

ENTRYPOINT ["/bin/sh", "/home/docker-start.sh"]

start.sh

#!/bin/sh

mv -n /app/* /data
rm /app -r
cd /data
npm start

现在该程序只需一行即可部署

docker run -v /opt/appname/ow:/data --name ow homosanians/appname