我正在尝试dockerize一个PHP应用程序。在dockerfile中,我下载存档,提取它,等等。

一切都很好。但是,如果发布了一个新版本,并且我更新了dockerfile,我必须重新安装应用程序,因为config.php会被覆盖。

因此,我认为我可以将该文件作为卷挂载,就像对数据库所做的那样。

我尝试了两种方法,用音量和直接路径。

docker-compose:

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:

这导致了错误:

我尝试用一个给定的路径,作为一个挂载的卷。

/src/docker/myapp/upload:/var/www/html/upload
/src/docker/myapp/upload:/var/www/html/config.php

然而,这两种方法都不起作用。对于挂载的卷,我看到创建了上传。

但它失败了:

/var/www/html/config.php\"造成\"不是目录\""

如果我用

/src/docker/myapp/upload/config.php:/var/www/html/config.php

Docker创建upload文件夹,然后创建config.php文件夹。不是文件。

或者是否有另一种方法来持久化配置?


当前回答

TL&DR: Docker默认所有挂载点到目录。如果你想确保你的文件被挂载到docker实例中,这个文件必须在docker-compose启动和运行之前已经存在。

解释:

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

在您的示例中,如果您希望挂载一个文件,请确保它已经存在于主机系统中。当Docker看到这个条目已经存在时,它会将这个文件挂载到Docker环境中。

其他回答

对我来说,问题是我指定了不正确的源文件。

这里有一个例子:

 robert ❱ ~ ❱ docker run --rm -it -v "${PWD}/non-existant:/root/destination" -w /root --entrypoint /usr/bin/ls ubuntu -lad destination
drwxr-xr-x 2 root root 64 Mar 29 05:54 destination
 robert ❱ ~ ❱ touch exists
 robert ❱ ~ ❱ docker run --rm -it -v "${PWD}/exists:/root/destination" -w /root --entrypoint /usr/bin/ls ubuntu -lad destination
-rw-r--r-- 1 root root 0 Mar 29 05:58 destination
 robert ❱ ~ ❱

TL;DR -这可能是你的拼写,就像我的拼写一样。

TL&DR: Docker默认所有挂载点到目录。如果你想确保你的文件被挂载到docker实例中,这个文件必须在docker-compose启动和运行之前已经存在。

解释:

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

在您的示例中,如果您希望挂载一个文件,请确保它已经存在于主机系统中。当Docker看到这个条目已经存在时,它会将这个文件挂载到Docker环境中。

我在Windows上也遇到了同样的问题,Docker 18.66.1 -ce-win73(19507)。

通过Docker设置面板删除并重新添加共享驱动器,一切都恢复正常了。

您可以挂载文件或目录/文件夹,这完全取决于源文件或目录。你还需要提供完整的路径或者如果你不确定你可以使用PWD。下面是一个简单的工作示例。

在这个例子中,我挂载了工作目录中已经存在的env-commands文件

$ docker run  --rm -it -v ${PWD}/env-commands:/env-commands aravindgv/eosdt:1.0.5 /bin/bash -c "cat /env-commands"

对于像我这样使用Windows容器的人来说,要知道不能使用Windows容器绑定或挂载单个文件。

The following examples will fail when using Windows-based containers, as the destination of a volume or bind mount inside the container must be one of: a non-existing or empty directory; or a drive other than C:. Further, the source of a bind mount must be a local directory, not a 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问题