重新创建docker bind-mount

时间:2018-07-22 21:13:21

标签: docker mount

如果在主机上绑定安装不存在的文件,则docker将在其位置愉快地创建一个目录并将其与容器共享。在“修复”错误后(例如,停止容器,用文件替换目录并启动容器),您将收到以下错误:

  

docker:来自守护程序的错误响应:oci运行时错误:container_linux.go:262:启动容器进程导致“ process_linux.go:339:容器初始化导致“ rootfs_linux.go:57:将” [snip]”安装到[snip] [“ snip]”处的“]”导致“不是目录”“”“   :您是否正在尝试将目录挂载到文件上(反之亦然)?检查指定的主机路径是否存在以及是否为预期的类型。

以下是从控制台复制的一些步骤:

# ensure test file does not exist
$ rm -f /test.txt

# run hello-world container with test.txt bind mount
$ docker run --name testctr -v /test.txt:/test.txt hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.
<snip>

# let's say what's in /
$ ls -l /

<snip>
dr-xr-xr-x   13 root     root             0 Jul 17 01:08 sys
drwxr-xr-x    2 root     root          4096 Jul 22 20:54 test.txt
drwxrwxrwt    1 root     root          4096 Jul 17 09:01 tmp
<snip>

# let's correct the mistake and run the container again
$ rm -rf /test.txt
$ touch /test.txt
$ docker start testctr

Error response from daemon: OCI runtime create failed: container_linux.go:348: starting
container process caused "process_linux.go:402: container init caused \"rootfs_linux.go:58:
mounting \\\"/test.txt\\\" to rootfs \\\"/var/lib/docker/overlay2/
26fd6981e919e5915c31098fc74551314c4f05ce6c5e175a8be6191e54b7f807/merged\\\" at \\\"/var/lib/
docker/overlay2/26fd6981e919e5915c31098fc74551314c4f05ce6c5e175a8be6191e54b7f807/merged/
test.txt\\\" caused \\\"not a directory\\\"\"": unknown: Are you trying to mount a directory
onto a file (or vice-versa)? Check if the specified host path exists and is the expected
type
Error: failed to start containers: testctr

请注意,即使我们在启动现有容器时遇到此错误,但创建一个新容器实际上仍然有效。

所以我的问题是,如何解决这个问题?我可以看到两种不同的可能性:

  • 重新创建容器:
    • 以某种方式将容器(docker run ...)创建为变量(?)的导出命令
    • 删除旧容器
    • 在步骤1中生成的运行命令
  • 以某种方式调整现有容器以固定支架
    • 这可能无法通过docker进行,因为显然绑定绑定不是由docker管理的

PS:这个问题也应该解决this one

1 个答案:

答案 0 :(得分:0)

为现有容器生成docker run ...的两个选项:

  • assaflavie/runlike-之所以要这样做,是因为另一个似乎在标签方面存在一些问题(但是该标签不支持批量检查)

    $ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike <container>
    
  • nexdrew/rekcod

    $ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod <container>
    

最终脚本看起来像( unested ):

# get names of running containers (names persist recreation)
running_containers=$(docker ps --format "{{.Names}}")

# stop running containers
docker stop $running_containers

# generate recreate script
containers=$(docker ps --all --format "{{.Names}}")
echo '#!/bin/sh' > ./recreate.sh
while read -r cname; do
  docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike "$cname" >> ./recreate.sh
done <<< "$containers"
chmod +x ./recreate.sh

# ... do some action now (maybe also manually check recreate script) ...

# recreate containers
docker rm --force $containers
./recreate.sh

# restart containers that were previously running
docker start $running_containers

这似乎可以满足我的需求,但是一些人指出,这些工具可能会缺少docker功能,甚至可能包含错误(例如,我已经注意到rekcod已经存在此错误),因此请谨慎使用。