运行 作为 Swarm 服务子项的容器

Running a container as child of Swarm service

我需要 运行 一个容器('child' 图像),它可以访问 GPU 以进行视频编码加速,但我还需要它由 Swarm 编排。下面的组合文件(堆栈文件)有效地启动了子图像,但是当堆栈被移除时,子容器将成为孤立的。我试图避免 运行ning Docker-in-Docker per Jérôme Petazzoni's excellent blog。为了将子容器链接到父服务,我是否缺少任何其他标签——允许 Swarm 通过父服务编排子容器?

version: "3.7"
services:
  parent-service:
    image: docker:stable
    entrypoint: [sh, -c]
    environment:
      TASK_NAME: '{{.Task.Name}}'
    command: >-
      'exec docker run
      --interactive
      --device=/dev/dri/renderD128:/dev/dri/renderD128
      --label com.docker.stack.namespace=$$(docker container inspect --format "{{index .Config.Labels \"com.docker.stack.namespace\"}}" $${TASK_NAME})
      --volumes-from=$${TASK_NAME}
      --rm
      child:latest'
    volumes:
      - type: bind
        source: /var/run/docker.sock
        target: /var/run/docker.sock

事实证明,这在 Docker 中非常简单,只要您保持 sidecar 容器(子容器)的 PI​​D 链完整并正确管理 OS 信号即可。如果 PID 链保持完整,子容器将在父服务终止时收到 SIGTERM 信号。我们遇到了 3 个必须处理的案例; 1.) 容器直接 运行 我们的应用程序,我们可以控制它以确保信号得到处理,2.) 容器应用程序是在 shell 下运行并正确处理信号的第 3 方应用程序,以及 3.)容器应用程序无法正确处理信号。

  1. 在这种情况下,您的应用程序是 PID 1,因此您确保它正确处理 SIGTERM 等信号并终止应用程序以避免僵尸容器。
  2. 在这种情况下,通过使用 'exec' 在 shell 下执行应用程序来维护 PID 链,这会将容器的 PID 1 从 shell 转换为应用程序。
  3. 对于最后一个案例,您可以使用 dumb-init 启动容器应用程序,它将代表应用程序管理信号。在这种情况下,确保 dumb-init 是 PID 1。