为什么我挂载的 docker 卷文件变成容器内的文件夹?

Why are my mounted docker volume files turning into folders inside the container?

场景是 docker inside/beside docker 通过套接字绑定,目的是为 C.I 提供易于部署和扩展的 运行ner 代理./C.D。工具(在本例中为 VSTS)。之所以这样设置,是因为我要测试的各种项目使用docker/compose到运行测试,配置一个C.I./C.D。 worker 多次与 docker/compose 兼容变得麻烦且耗时。 (这最终将部署到 4+ Kubernetes 集群)

总之,问题:

复制步骤

  1. 运行 vsts-agent 图片

docker run \ -it \ -v /var/run/docker.sock:/var/run/docker.sock \ nullvoxpopuli/vsts-agent-with-aws-ecr:latest \ /bin/bash

  1. 运行 另一个图像(模拟 docker/compose 运行ning 测试)

echo 'test' > test-file.txt docker run -it -v file-test.txt:/file-test.txt busybox /bin/sh

  1. 检查是否存在测试-file.txt

cd / ls -la # shows that test-file.txt is a directory

所以,
- 为什么文件被挂载为容器内的文件夹?
- 我需要做什么才能正确安装卷?

解决方案 A - 感谢@BMitch

# On Host machine
docker run -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /tmp/vsts/work/:/tmp/vsts/work \
   nullvoxpopuli/vsts-agent-with-aws-ecr:latest \
   /bin/bash

# In vsts-agent-with-aws-ecr
cd /tmp/vsts/work/
git clone https://NullVoxPopuli@bitbucket.org/group/project.git
cd project/
./scripts/run/eslint.sh
# Success! (this uses docker-compose to map files to the node-based docker image)

Docker 从 docker 主机创建容器并装载卷。任何时候卷安装中的文件或目录不存在时,它都会被初始化为一个空目录。因此,如果您是从容器内部到 docker 套接字的 运行 docker 命令,这些命令将在 docker 主机上的容器外部进行解释,而文件不会存在。此外,docker run 命令需要主机卷时要安装的卷的完整路径,否则它会被解释为命名卷。

此时您可能想要做的是:

docker volume rm file-test.txt
docker run -it -v $(pwd)/file-test.txt:/file-test.txt busybox /bin/sh

相反,如果您尝试将文件从容器内部包含到另一个容器中,则可以使用这样的输入重定向来初始化命名卷:

tar -cC . . | docker run -i --rm -v file-test:/target busybox tar -xC /target
docker run -it -v file-test:/data busybox /bin/sh

使用 tar 将当前目录的内容复制到 stdout,由交互式 docker 命令处理,然后将这些目录内容提取到 /target 中容器,它是一个命名卷。请注意,在第二个示例中我没有将卷挂载到根目录中,因为命名卷是目录并且我不想替换根文件系统。

另一种选择是在 docker 主机上的多个容器之间共享一个卷挂载点,这样您在一个容器内编辑的文件就会到达主机,在那里它们被挂载到另一个容器中并在那里可见:

docker run \
  -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /container-data:/container-data \
  nullvoxpopuli/vsts-agent-with-aws-ecr:latest \
  /bin/bash
echo 'test' > /container-data/test-file.txt
docker run -it -v /container-data:/container-data busybox /bin/sh

如果容器 运行 时这些文件可能会被修改,我不建议将单个文件装载到容器中。文件更改通常会导致 inode 发生变化,docker 会将旧的 inode 挂载到容器中。因此,容器内部或外部对文件所做的更改在另一侧可能看不到,并且如果您修改容器内部的文件,则删除容器时可能会丢失该更改。 inode问题的解决方法是将整个目录挂载到容器中。