我正在尝试将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:
导致错误:
我用给定的路径尝试了它,作为已装载的音量。
/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创建上传文件夹,然后创建config.php文件夹。不是档案。
或者还有其他方法可以保留配置吗?
答案 0 :(得分:164)
TL; DR /说明:
如果您遇到正在创建的目录而不是尝试安装的文件,则可能无法提供有效和绝对路径。这是一个沉默且令人困惑的失败模式的常见错误。
文件卷在docker中以这种方式完成(绝对路径示例(可以使用env变量),你需要提到文件名):
volumes:
- /src/docker/myapp/upload:/var/www/html/upload
- /src/docker/myapp/upload/config.php:/var/www/html/config.php
你也可以这样做:
volumes:
- ${PWD}/upload:/var/www/html/upload
- ${PWD}/upload/config.php:/var/www/html/config.php
如果您从/src/docker/myapp
文件夹
答案 1 :(得分:60)
我一直在遭遇类似的问题。我试图将配置文件导入我的容器,这样我就可以在每次需要时修复它而无需重新构建图像。
我的意思是我认为以下命令会将$(pwd)/config.py
从Docker主机映射到容器/root/app/config.py
作为文件。
docker run -v $(pwd)/config.py:/root/app/config.py my_docker_image
但是,它始终创建一个名为config.py
的目录,而不是文件。
在寻找线索时,我找到了原因(来自here)
如果使用-v或--volume来绑定挂载文件或目录 在Docker主机上尚不存在,-v将为您创建端点。 始终将其创建为目录。
因此,它始终作为目录创建,因为我的泊坞主机没有$(pwd)/config.py
。
即使我在docker host中创建config.py也是如此。
$(pwd)/config.py
只是覆盖/root/app/config.py
而不是导出/root/app/config.py
。
答案 2 :(得分:14)
从docker-compose文件版本3.2开始,您可以指定类型为“ bind”的卷挂载(而不是默认类型的“ volume”),该挂载允许您将单个文件挂载到容器。在docker-compose卷文档中搜索“ bind mount”: https://docs.docker.com/compose/compose-file/#volumes
就我而言,我试图将单个“ .secrets”文件装载到应用程序中,该文件仅包含用于本地开发和测试的机密。在生产中,我的应用程序改为从AWS获取这些机密。
如果我使用简写语法将此文件作为卷安装:
volumes:
- ./.secrets:/data/app/.secrets
Docker会在容器内部创建一个“ .secrets” 目录,而不是映射到容器外部的文件。然后,我的代码将引发类似“ IsADirectoryError:[Errno 21]是目录:'。secrets'”的错误。
我改用了长句语法,使用只读的“绑定”卷安装指定了我的秘密文件:
volumes:
- type: bind
source: ./.secrets
target: /data/app/.secrets
read_only: true
现在Docker可以将我的.secrets文件正确地安装到容器中,并在容器中创建文件而不是目录。
答案 3 :(得分:8)
以上所有答案都是正确的。
但我发现真正有用的一件事是挂载的文件应该提前存在于 docker 主机中 否则 docker 将创建一个目录。
例如:
/a/file/inside/host/hostFile.txt:/a/file/inside/container/containerFile.txt
hostFile.txt
应该提前存在。
否则您将收到此错误:containerFile.txt is a directory
答案 4 :(得分:7)
对我有用的方法是使用bind
坐骑
version: "3.7"
services:
app:
image: app:latest
volumes:
- type: bind
source: ./sourceFile.yaml
target: /location/targetFile.yaml
感谢迈克的品种在Mount single file from volume using docker-compose
给出的答案您需要使用“长语法”表示bind
挂载:https://docs.docker.com/compose/compose-file/#long-syntax
答案 5 :(得分:2)
对于像我这样使用Windows容器的任何人,请知道您不能使用Windows容器绑定或装入单个文件。
以下示例在使用基于Windows的容器时将失败,因为容器内的卷或绑定安装的目的地必须是以下位置之一:不存在或空目录;或C:以外的驱动器。此外,绑定安装的源必须是本地目录,而不是文件。
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 ...
很难发现,但it's there
Link to the Github issue regarding mapping files into Windows container
答案 6 :(得分:1)
您还可以像这样使用trace(mlogit:::model.matrix.mFormula, edit=TRUE)
文件的相对路径(在Windows主机,Linux容器上测试):
docker-compose.yml
答案 7 :(得分:0)
对我来说,问题是我试图装载到容器中的文件上的符号链接损坏了
答案 8 :(得分:0)
我在Windows Docker 18.06.1-ce-win73 (19507)
上遇到了同样的问题。
通过Docker设置面板删除并重新添加共享驱动器,一切再次正常运行。
答案 9 :(得分:0)
使用安装代替卷(-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高山sh
答案 10 :(得分:0)
在Windows中, 如果需要在docker-compose.yml中使用$ {PWD} env变量,则可以在与docker-compose.yml文件相同的目录中创建一个.env文件,然后手动插入文件夹的位置。
CMD(pwd_var.bat):
echo PWD=%cd% >> .env
Powershell(pwd_var.ps1):
$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'; echo "PWD=$(get-location).path" >> .env
对于docker-compose .env变量,还有更多不错的功能:
https://docs.docker.com/compose/reference/envvars/尤其适用于COMPOSE_CONVERT_WINDOWS_PATHS
env变量,该变量允许docker compose接受带有baskslash "\"
的Windows路径。
要在Windows上共享文件时,在与容器共享文件之前,该文件必须存在。
答案 11 :(得分:0)
您可以挂载文件或目录/文件夹,这完全取决于源文件或目录。另外,您还需要提供完整路径,或者如果不确定是否可以使用PWD。这是一个简单的工作示例。
在此示例中,我正在挂载工作目录中已经存在的env-commands文件
$ docker run --rm -it -v ${PWD}/env-commands:/env-commands aravindgv/eosdt:1.0.5 /bin/bash -c "cat /env-commands"
答案 12 :(得分:0)
我遇到了同样的问题,docker-compose正在创建目录而不是文件,然后在中途崩溃。
我做了什么:
运行容器而不映射文件
将配置文件复制到主机位置:
docker cp containername:/var/www/html/config.php ./config.php
删除容器(docker-compose下来)
放回映射并重新安装容器
docker compose将找到配置文件,并将其映射,而不是尝试创建目录。
答案 13 :(得分:0)
对于使用Mac的Docker桌面的用户: 如果文件存在于本地文件系统中,但已作为目录挂载在容器内,则可能是您未与Docker Desktop共享文件/目录。 您需要检查Docker Desktop文件共享设置:
注意!不要将根目录或任何系统目录添加到文件共享设置中,因为这会加载CPU。 Github中对此问题进行了描述,this comment提供了一种解决方法。
答案 14 :(得分:-1)
我在Windows 8.1上遇到相同的问题
原来,这是由于路径的大小写敏感所致。
我从目录docker-compose up
调用了cd /c/users/alex/
,然后在容器中将文件转换为目录。
但是当我做cd /c/Users/alex/
(不是大写的用户)并从那里打电话给docker-compose up
时,它起作用了。
在我的系统中,User dir和Alex dir都大写,尽管似乎只有Users dir很重要。
答案 15 :(得分:-2)
也许这可以帮助某人。
我遇到了这个问题,并尝试了一切。卷绑定看起来很好,即使我挂载了目录(不是文件),我在挂载的目录中也有正确的文件名,但是挂载为目录。
我试图重新启用共享驱动器,而Docker抱怨防火墙处于活动状态。
禁用防火墙后,一切正常。