Docker 如何在卷中装入单个文件

Docker 如何在卷中装入单个文件,docker,docker-compose,Docker,Docker Compose,我正在尝试对一个PHP应用程序进行dockerize。在dockerfile中,我下载归档文件,解压缩它,等等 一切正常。但是,如果发布了新版本并且我更新了dockerfile,我必须重新安装应用程序,因为config.php会被覆盖 所以我想我可以像装载数据库一样,将文件装载为卷 我尝试了两种方法,一种是卷,另一种是直接路径 docker compose: 版本:“2” 服务: 应用程序: 构建:src 端口: - "8080:80" 取决于: -mysql 卷数: -app conf:/va

我正在尝试对一个PHP应用程序进行dockerize。在dockerfile中,我下载归档文件,解压缩它,等等

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

所以我想我可以像装载数据库一样,将文件装载为卷

我尝试了两种方法,一种是卷,另一种是直接路径

docker compose:

版本:“2”
服务:
应用程序:
构建:src
端口:
- "8080:80"
取决于:
-mysql
卷数:
-app conf:/var/www/html/upload
-app conf:/var/www/html/config.php
环境:
数据库类型:mysql
数据库管理器:MysqlManager
mysql:
图片:mysql:5.6
容器名称:mysql
卷数:
-mysqldata:/var/lib/mysql
端口:
- 3306:3306
环境:
MYSQL\u ROOT\u密码:
MYSQL\u数据库:
MYSQL\u用户:
MYSQL\u密码:
卷数:
mysqldata:
应用程序配置:
这会导致错误:

我试着用一个给定的路径,作为一个装入的卷

/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中是这样完成的(绝对路径示例(可以使用env变量),并且您需要提及文件名):

您还可以执行以下操作:

    volumes:
      - ${PWD}/upload:/var/www/html/upload
      - ${PWD}/upload/config.php:/var/www/html/config.php

如果您从
/src/docker/myapp
文件夹

启动docker compose,我也遇到了类似的问题。我正在尝试将配置文件导入到容器中,以便在每次需要时都可以修复它,而无需重新构建映像

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

docker run -v $(pwd)/config.py:/root/app/config.py my_docker_image
但是,它总是创建一个名为
config.py
的目录,而不是一个文件

在寻找线索的过程中,我找到了原因(来源)

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

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

即使我在docker主机中创建config.py。
$(pwd)/config.py
只是覆盖了
/root/app/config.py
没有导出
/root/app/config.py
对我来说,问题是我试图装入容器的文件上有一个断开的符号链接

我在Windows 8.1上也有同样的问题

结果表明,这是由于path的大小写敏感性。 我从目录
cd/c/users/alex/
中调用了
docker compose up
,在容器中,一个文件被转换为目录

但是当我做了
cd/c/Users/alex/
(不是大写的Users)并从那里调用
docker compose-up
时,它成功了


在我的系统中,Users dir和Alex dir都是大写的,尽管看起来只有Users dir才重要。

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


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

使用挂载(
--mount
)代替卷(
-v

更多信息:

例子: 确保docker主机上存在/tmp/a.txt

docker run -it --mount type=bind,source=/tmp/a.txt,target=/root/a.txt alpine sh
在窗户里, 如果需要docker-compose.yml中的${PWD}env变量,可以在docker-compose.yml文件所在的目录中创建一个.env文件,然后手动插入文件夹的位置

指令(pwd_变量bat):

Powershell(pwd_变量ps1):

docker compose.env变量还有更多好的特性: 特别是对于
COMPOSE\u CONVERT\u WINDOWS\u路径
env变量,该变量允许docker COMPOSE使用baskslash
“\”
接受WINDOWS路径


当您想在windows上共享文件时,在与容器共享之前,该文件必须存在。

对于像我这样使用windows容器的人,请知道您不能使用windows容器绑定或装载单个文件

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

net使用z:\\remotemachine\share

docker-run-vz:\foo:c:\dest…

docker run-v\\uncpath\to\目录:c:\dest…

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

docker-run-vc:\foo:c:…

docker run-v c:\foo:c:\包含内容的现有目录…

很难发现,但是


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

卷:
-./test.conf:/fluentd/etc/test.conf

也许这对某人有帮助

我遇到了这个问题并尝试了所有方法。卷绑定看起来很好,即使我挂载了目录(不是文件),我在挂载目录中的文件名也正确,但挂载为dir

我试图重新启用共享驱动器,Docker抱怨防火墙处于活动状态

禁用防火墙后,所有的防火墙都是w
docker run -it --mount type=bind,source=/tmp/a.txt,target=/root/a.txt alpine sh
echo PWD=%cd% >> .env
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'; echo "PWD=$(get-location).path" >> .env
  version: "3.7"    
  services:
  app:
    image: app:latest
    volumes:
      - type: bind
        source: ./sourceFile.yaml
        target: /location/targetFile.yaml
$ docker run  --rm -it -v ${PWD}/env-commands:/env-commands aravindgv/eosdt:1.0.5 /bin/bash -c "cat /env-commands"
/a/file/inside/host/hostFile.txt:/a/file/inside/container/containerFile.txt