代码之家  ›  专栏  ›  技术社区  ›  Christian

重新创建docker绑定装载

  •  0
  • Christian  · 技术社区  · 6 年前

    如果您绑定了一个不存在的文件(在主机上),DOCKER将愉快地在它的位置创建一个目录并与容器共享它。在“修复”错误时(即停止容器,用文件替换目录并启动容器),您将得到以下错误:

    Docker:守护进程的错误响应:OCI运行时错误:container_Linux.go:262:启动容器进程导致“process_Linux.go:339:container init导致“rootfs_Linux.go:57:将“[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管理的

    附言:这个问题也应该解决 this one .

    1 回复  |  直到 6 年前
        1
  •  0
  •   Christian    6 年前

    生成的两个选项 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>
      

    最后的剧本看起来像( 未经测试 )以下内容:

    # 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特性,甚至可能包含bug(例如,我已经注意到RekCod中的错误),所以请谨慎使用。