【问题标题】:Is it possible to start a stopped container from another container是否可以从另一个容器启动已停止的容器
【发布时间】:2021-05-25 05:20:41
【问题描述】:

有两个容器 A 和 B。一旦容器 A 启动,将执行一个进程,然后容器将停止。容器 B 只是一个 Web 应用程序(比如 expressjs)。是否可以从容器 B 启动 A ?

【问题讨论】:

    标签: docker docker-container


    【解决方案1】:

    可以授予容器对 docker 的访问权限,以便它可以在您的主机上生成其他容器。您可以通过暴露容器内的 docker 套接字来做到这一点,例如:

    docker run -v /var/run/docker.sock:/var/run/docker.sock --name containerB myimage ...
    

    现在,如果您在容器内有可用的docker 客户端,您将能够控制主机上的 docker 守护程序并使用它来生成您的“容器 A”。

    在尝试此方法之前,您应该了解安全注意事项:访问 docker 与在主机上拥有 root 访问权限相同,这意味着如果您的 Web 应用程序有远程入侵,您刚刚将密钥交给攻击者的主机。这在in this article 中有更完整的描述。

    【讨论】:

    • 我遵循了这个提示。然后我手动将dockerdocker-compose 复制到容器中。 docker-compose 在容器内运行良好。但是,我需要将/usr/lib/x86_64-linux-gnu/libltdl.so.7.3.1 从我的主机复制到容器中,然后在容器内我通过ln -sf /usr/lib/x86_64-linux-gnu/libltdl.so.7.3.1 /usr/lib/x86_64-linux-gnu/libltdl.so.7 创建一个符号链接。在容器内:ldd /usr/bin/docker 所有库现在都已解析,我可以在容器内运行 dockerdocker-cocmpose
    • 我的容器中安装了 docker 客户端并公开了主机系统的 docker 套接字,但是当我尝试从容器内启动容器时,我收到“尝试连接时拒绝权限” docker 守护进程套接字”。我在构建容器时做了“usermod -a -G docker $user”。 $user 在容器外不存在。有什么建议吗?我在这里提问而不是添加一个新问题,因为我觉得它可能是对这个答案的有效甚至必要的补充。
    • 看来问题是容器的gid和主机docker不一样。 Dockerfile 中的groupmod -g <host gid> docker 修复了它。
    【解决方案2】:

    可以通过安装 docker socket 来实现。

    容器 A
    它会将时间打印到标准输出(及其日志)并退出。

    docker run --name contA ubuntu date
    

    容器 B
    诀窍是安装主机的 docker 套接字,然后在容器上安装 docker 客户端。然后它将与守护进程交互,就像您在主机上使用 docker 一样。安装 docker 后,它只需每 5 秒重启一次容器 A。

    docker run --name contB -v /var/run/docker.sock:/var/run/docker.sock ubuntu bash -c "
    apt-get update && apt-get install -y curl &&
    curl -sSL https://get.docker.com/ | sh && 
    watch --interval 5 docker restart contA"
    

    您可以通过查看 contA 的日志看到它正在被调用

    docker logs contA
    

    也就是说,Docker 确实适用于长时间运行的服务。在 Docker github 问题上有一些关于为维护、cron 作业等指定短期“作业”服务的讨论,但没有任何决定,更不用说编码了。因此,最好构建您的系统,以便容器能够正常运行。

    【讨论】:

    • 我没有立即发布我的答案,所以@larsks 首先出现。无论如何我都会把它放在这里,因为它有你可能会觉得有用的代码。
    • 它有效。我不确定在 docker 中安装 docker 是否是个好主意,那将是另一个问题。由于@larsks 最先出现,我只是打勾。
    • 它可以工作,但代码对我来说不是很清楚。我对get.docker.com 的使用感到困惑。无论如何,必须在 docker 容器内安装 docker-ce( apt-get install docker-ce ),然后使用“docker restart containername”重新启动另一个 docker 容器
    【解决方案3】:

    docker-compose.yml(感谢 larsks)

    # ...
            volumes:
                - /var/run/docker.sock:/var/run/docker.sock
    # ...
    

    Dockerfile(感谢 Aaron V)

    # ...
    
    ENV DOCKERVERSION=19.03.12
    RUN curl -fsSLO https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKERVERSION}.tgz \
      && tar xzvf docker-${DOCKERVERSION}.tgz --strip 1 -C /usr/local/bin docker/docker \
      && rm docker-${DOCKERVERSION}.tgz
    
    # ...
    

    Node.js index.js(感谢 Arpan Abhishek、Maulik Parmar 和 anishsane)

    # ...
    
    const { exec } = require("child_process");
    
    # ...
    
            exec('docker container ls -a --format "table {{.ID}}\t{{.Names}}" | grep <PART_OF_YOUR_CONTAINER_NAME> | cut -d" " -f1 | cut -f1 | xargs -I{} docker container restart -t 0 {}', (error, stdout, stderr) => {
                if (error) {
                    console.log(`error: ${error.message}`);
                    return;
                }
                if (stderr) {
                    console.log(`stderr: ${stderr}`);
                    return;
                }
                console.log(`stdout: ${stdout}`);
            });
    
    # ...
    
    • 请确保您的应用程序至少有密码保护。以任何方式暴露 docker.sock 都是安全的事情。
    • 在这里您可以找到其他 Docker 客户端版本:https://download.docker.com/linux/static/stable/x86_64/
    • 请将&lt;PART_OF_YOUR_CONTAINER_NAME&gt; 替换为您的容器名称的一部分。

    【讨论】:

      猜你喜欢
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-23
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      相关资源
      最近更新 更多