如何在卷中装入单个文件

Jak*_*zak 182 docker docker-compose

我试图将一个php应用程序停靠.在dockerfile中我下载了存档,提取它等.

一切正常,但是如果新版本发布,我更新dockerfile我必须重新安装应用程序,因为config.php被覆盖.

所以我认为我可以将文件挂载为卷,就像我对数据库一样.

我尝试了两种方式,包括音量和直接路径.

泊坞窗 - 撰写:

version: '2'
services:
  app:
    build: src
    ports:
      - "8080:80"
    depends_on:
      - mysql
    volumes:
      -  app-conf:/var/www/html/upload
      -  app-conf:/var/www/html/config.php
    environment:
      DB_TYPE: mysql
      DB_MANAGER: MysqlManager

  mysql:
    image: mysql:5.6
    container_name: mysql
    volumes:
      - mysqldata:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD:
      MYSQL_DATABASE:
      MYSQL_USER:
      MYSQL_PASSWORD:

volumes:
  mysqldata:
  app-conf:
Run Code Online (Sandbox Code Playgroud)

这导致错误:

我用一个给定的路径尝试了它,作为一个装载的音量.

/src/docker/myapp/upload:/var/www/html/upload
/src/docker/myapp/upload:/var/www/html/config.php
Run Code Online (Sandbox Code Playgroud)

但是两种方式都不起作用.使用已安装的卷,我看到上传已创建.

但随后失败了

/var/www/html/config.php \\"导致\\"不是目录\\"\""

如果我用/src/docker/myapp/upload/config.php:/var/www/html/config.php试试

Docker创建上传文件夹,然后创建config.php文件夹.不是文件.

或者还有另一种方法来保持配置?

Bla*_*ork 239

文件卷在docker中以这种方式完成(绝对路径示例(可以使用env变量),你需要提到文件名):

    volumes:
      - /src/docker/myapp/upload:/var/www/html/upload
      - /src/docker/myapp/upload/config.php:/var/www/html/config.php
Run Code Online (Sandbox Code Playgroud)

你也可以这样做:

    volumes:
      - ${PWD}/upload:/var/www/html/upload
      - ${PWD}/upload/config.php:/var/www/html/config.php
Run Code Online (Sandbox Code Playgroud)

如果从/src/docker/myapp文件夹中触发docker-compose

  • 就像我说的,如果我尝试/src/docker/myapp/upload/config.php:/var/www/html/config.php Docker创建上传文件夹,然后创建config.php文件夹.不是文件. (68认同)
  • 如果主机docker中不存在/src/docker/myapp/upload/config.php将创建一个文件夹...我正在做的是创建一个在运行docker run之前创建一个空文件的脚本 - 将是理想的如果我可以通过cmd line args指示docker为我做这件事. (13认同)
  • 为了实现这一点,我必须提供绝对路径.使用PWD的技巧在这里帮助很多,谢谢! (11认同)
  • 在你的帖子中你写的不同.如果文件在那里它应该作为文件挂载. (9认同)
  • 对我来说是创建一个文件夹而不是文件,但我认为因为该文件后来在该路径中被复制,无论如何都要推迟绑定? (4认同)
  • 只需使用相对路径 `-./src/foo:/etc/foo`,因为 PWD 在 Windows 上未定义,而 `-/` 在 Linux 和 Windows 上有效。路径是相对于 docker 文件的。 (4认同)
  • 在 Linux 上使用 `$(pwd)` 代替 `${PWD}` (2认同)
  • 如果卷不存在,docker 会拒绝启动容器,那么事情会变得更容易吗?并附上一条有用的信息。不是吗?所有这些都是不必要的,并且不会创建我的用户帐户下“root”拥有的许多目录。(例如,对于 dev,将“${PWD}/storage”挂载到容器中,但它不存在。现在它存在,由 root 拥有,因为 docker 创建了它。) (2认同)

San*_*Kim 69

我一直在遭遇类似的问题.我试图将我的配置文件导入到我的容器中,以便我可以在每次需要时修复它而无需重新构建映像.

我的意思是我认为下面的命令会$(pwd)/config.py从Docker主机映射/root/app/config.py到容器作为文件.

docker run -v $(pwd)/config.py:/root/app/config.py my_docker_image
Run Code Online (Sandbox Code Playgroud)

但是,它始终创建一个名为的目录config.py,而不是文件.

在寻找线索的同时,我找到了原因(从这里开始)

如果使用-v或--volume绑定装载Docker主机上尚不存在的文件或目录,-v将为您创建端点. 它始终作为目录创建.

因此,它始终作为目录创建,因为我的docker主机没有$(pwd)/config.py.

即使我在docker host中创建config.py. $(pwd)/config.py只是过度/root/app/config.py而不是出口/root/app/config.py.

  • 我刚刚在`Dockerfile`中添加了一个`touch path/to/file`,当我挂载它时仍然是一个文件(不是创建的目录) (12认同)
  • `:`的左侧必须是完整的路径.它以这种方式工作 (4认同)
  • “touch”就是答案,在 Dockerfile 中执行此操作,然后您的 docker-compose 卷挂载将正常工作,而无需创建目录 (2认同)

Tet*_*Dev 44

对我有用的方法是使用bind支架

  version: "3.7"    
  services:
  app:
    image: app:latest
    volumes:
      - type: bind
        source: ./sourceFile.yaml
        target: /location/targetFile.yaml
Run Code Online (Sandbox Code Playgroud)

感谢迈克品种的回答:使用 docker-compose 从卷中挂载单个文件

您需要使用“长语法”来表达bind使用volumes密钥的挂载:https : //docs.docker.com/compose/compose-file/compose-file-v3/#long-syntax-1

  • 这个答案比上面的更简洁,并且完全符合我的需要。谢谢。 (4认同)

小智 27

从 docker-compose 文件版本 3.2 开始,您可以指定“bind”类型(而不是默认类型“volume”)的卷挂载,允许您将单个文件挂载到容器中。在 docker-compose volume 文档中搜索“bind mount”:https : //docs.docker.com/compose/compose-file/#volumes

就我而言,我试图将单个“.secrets”文件装入我的应用程序,其中包含仅用于本地开发和测试的机密。在生产中,我的应用程序改为从 AWS 获取这些机密。

如果我使用速记语法将此文件安装为卷:

volumes:
 - ./.secrets:/data/app/.secrets
Run Code Online (Sandbox Code Playgroud)

Docker 会在容器内创建一个“.secrets”目录,而不是映射到容器外的文件。然后我的代码会引发类似“IsADirectoryError: [Errno 21] Is a directory: '.secrets'”的错误。

我通过使用长手语法解决了这个问题,使用只读“绑定”卷安装指定我的秘密文件:

volumes:
 - type: bind
   source: ./.secrets
   target: /data/app/.secrets
   read_only: true
Run Code Online (Sandbox Code Playgroud)

现在 Docker 正确地将我的 .secrets 文件安装到容器中,在容器内创建一个文件而不是目录。


Dan*_*iel 13

您还可以docker-compose.yml像这样在文件中使用相对路径(在 Windows 主机、Linux 容器上测试):

volumes:
    - ./test.conf:/fluentd/etc/test.conf
Run Code Online (Sandbox Code Playgroud)

  • 我仍然得到一个目录而不是文件。 (14认同)
  • 我在 Mac 上使用 docker-compose 版本 1.24.1、构建版本 4667896b 在“docker-compose.yml”文件中指定的“version: '3.7”进行了测试,并且它有效。 (2认同)

Ehs*_*har 11

以上所有答案都是正确的。

但我发现真正有用的一件事是,挂载的文件应该提前存在于 docker 主机中,否则 docker 将创建一个目录。

例如:

/a/file/inside/host/hostFile.txt:/a/file/inside/container/containerFile.txt
Run Code Online (Sandbox Code Playgroud)

hostFile.txt应该提前存在。否则你会收到这个错误:containerFile.txt is a directory


小智 8

使用mount--mount)代替volume-v

更多信息:https : //docs.docker.com/storage/bind-mounts/

例:

确保Docker主机上存在/tmp/a.txt

docker run -it --mount type=bind,source=/tmp/a.txt,target=/root/a.txt alpine sh
Run Code Online (Sandbox Code Playgroud)

  • 我不知道如何将其转换为 docker-compose。'帮助不大? (3认同)
  • 这并不能真正回答问题。*volumes* 也可以工作(因为问题出在绝对路径中)。`--mount` 和 `-v` 之间的唯一区别是卷的主机部分尚不存在时的行为。根据您的链接:>如果您使用 -v 或 --volume 绑定安装 Docker 主机上尚不存在的文件或目录,则 -v 会为您创建端点。它始终创建为目录。 (2认同)

Jus*_*ard 7

对于像我这样使用Windows容器的任何人,请知道您不能使用Windows容器绑定或装入单个文件。

当使用基于Windows的容器时,以下示例将失败,因为容器内的卷或绑定安装的目的地必须是以下位置之一:不存在或空目录;或C:以外的驱动器。此外,绑定安装的源必须是本地目录,而不是file

net use z: \\remotemachine\share

docker run -v z:\foo:c:\dest ...

docker run -v \\uncpath\to\directory:c:\dest ...

docker run -v c:\foo\somefile.txt:c:\dest ...

docker run -v c:\foo:c: ...

docker run -v c:\foo:c:\existing-directory-with-contents ...

很难发现,但是在那里

链接到有关将文件映射到Windows容器的Github问题

  • 不知道2020年7月还这样吗? (2认同)
  • @OvidiuBuligan 是的。根据 docker 开发人员对此问题的评论,无论如何,最好还是挂载目录,即使在 Linux 上也是如此。他们还表示,如果不进行大规模重写,他们就不能允许这种行为。所以我真的怀疑我们会在中短期内看到这种情况。 (2认同)

Aff*_*lem 5

在撰写中,我使用相对路径并且它有效:

version: "3.7"
services:
    svc1: 
      volumes:
        # Current dir is parent of src
        - "./src/file.conf:/path/in/container/file.conf 
Run Code Online (Sandbox Code Playgroud)

使用docker run命令绑定挂载文件会产生:

docker: Error response from daemon: invalid mount config for type "bind": invalid mount path: 'path/file.conf' mount path must be absolute. 
See 'docker run --help'.
Run Code Online (Sandbox Code Playgroud)

显然,执行此操作的唯一方法是指定绝对安装路径,如下所示:

docker run -it --rm --mount type=bind,source="/path/to/file.conf",target=/file.conf alpine sh
Run Code Online (Sandbox Code Playgroud)

"%cd%"对于Windows 用户Linux 用户来说,"$(pwd)"也是一种处理绝对路径的方法。

请参阅存储绑定安装

对于 Visual Studio Code 用户,请确保在命令提示符终端中运行 %cd% 命令,而不是 PowerShell。


Fly*_*ngV 5

TL&DR: Docker 默认所有挂载点到目录。如果要确保文件已安装到 docker 实例中,则该文件必须在 docker-compose 启动并运行之前已存在。

解释:

传统上,安装卷的目的始终意味着将存储位置安装到目录。然而,现在这种情况正在改变,现在只能共享文件。从程序员的角度来看,很难知道“/tmp/something”是文件还是目录。因此,Docker 假定所有挂载点首先都是一个目录,除非该文件已经存在。

在您的示例中,如果您想要安装文件,请确保它已存在于主机系统上。当 Docker 发现该条目已经存在时,它将将该文件挂载到 docker 环境中。


归档时间:

查看次数:

184422 次

最近记录:

6 年,1 月 前