重新创建 docker 绑定安装
Recreating docker bind-mount
如果您绑定挂载一个不存在的文件(在主机上),docker 将愉快地在其位置创建一个目录并与容器共享。在 "fixing" 错误(即停止容器,用文件替换目录并启动容器)时,您将收到以下错误:
docker: Error response from daemon: oci runtime error: container_linux.go:262: starting container process caused "process_linux.go:339: container init caused "rootfs_linux.go:57: mounting "[snip]" to [snip]" at "[snip]" caused "not a directory"""
: 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.
以下是从控制台重现的一些步骤:
# 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.
为现有容器生成 docker run ...
的两个选项:
assaflavie/runlike - 我选择了这个,因为另一个标签似乎有一些问题(但这个不支持批量检查)
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike <container>
-
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod <container>
最终脚本看起来像 (未测试):
# 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 中注意到了这一点),因此请谨慎使用.
如果您绑定挂载一个不存在的文件(在主机上),docker 将愉快地在其位置创建一个目录并与容器共享。在 "fixing" 错误(即停止容器,用文件替换目录并启动容器)时,您将收到以下错误:
docker: Error response from daemon: oci runtime error: container_linux.go:262: starting container process caused "process_linux.go:339: container init caused "rootfs_linux.go:57: mounting "[snip]" to [snip]" at "[snip]" caused "not a directory""" : 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.
以下是从控制台重现的一些步骤:
# 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.
为现有容器生成 docker run ...
的两个选项:
assaflavie/runlike - 我选择了这个,因为另一个标签似乎有一些问题(但这个不支持批量检查)
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock assaflavie/runlike <container>
-
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock nexdrew/rekcod <container>
最终脚本看起来像 (未测试):
# 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 中注意到了这一点),因此请谨慎使用.