Supervisord 仅以 Docker-Compose 开头

Supervisord only starts with Docker-Compose

我有以下 Dockerfile,其中对 Nginx 服务器进行了一些自定义。我使用 docker build -t nginx-custom:1.21.1 . 命令构建图像,没有错误。但是当我想使用 docker run -it -d nginx-custom:1.21.1 /bin/bash 命令从此图像创建容器时也不会出现任何错误。但是当我使用 docker exec 命令进入容器并使用 ps -ef 检查 运行 进程时,结果仅包含 bash 进程。

FROM nginx:1.21.1 AS nginx-base

RUN set -x \
    && apt-get update \
    && apt-get install --no-install-recommends --no-install-suggests -y man nano procps ca-certificates wget gnupg gnupg2 iputils-ping net-tools supervisor \
    && apt-get clean autoclean \
    && apt-get autoremove --yes \
    && rm -rf /var/lib/{apt,dpkg,cache,log}/

EXPOSE  80 443

WORKDIR /var/www

COPY config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["service supervisor restart"]

FROM nginx-base AS nginx-config

# Replace the original Nginx config file
COPY config/nginx.conf /etc/nginx/nginx.conf

# Test HTML file
COPY scripts/index.html /var/www/html/index.html

在一些失败之后,我创建了一个包含以下内容的撰写文件和 运行 下一个命令:docker-compose up -d --build 然后一切正常。所有必要的过程都是运行.

version: '3.8'

services:
  nginx-custom:
    tty: true
    build:
      context: .
      dockerfile: Dockerfile
    image: nginx-custom:1.21.1
    container_name: nginx-custom
    networks:
      devnet:
        ipv4_address: 172.18.0.4
    restart: unless-stopped

networks:
  devnet:
    external: true

有谁知道为什么 Supervisor 只能这样工作?

一个Docker容器只有运行一个进程。如果你需要在一个容器中 运行 多个进程,你需要一些像 supervisord 这样的进程管理器,但这通常被认为是一种反模式。标准 Docker Hub 图像大致分为三种:基本 OS 图像(alpineubuntu);语言工具链和 运行 次(pythonnodegolang);以及 运行 一些实际程序 (postgresqlnginx) 的东西。在最后一种情况下,基础映像已经配置为 运行 作为单个主容器进程的程序。

这意味着您可以将 Docker 文件减少到

FROM nginx:1.21.1
COPY config/nginx.conf /etc/nginx/nginx.conf
COPY scripts/index.html /var/www/html/index.html

并且基本图像已经有一个正确的 CMD。您不需要文本编辑器、手册页或低级网络调试工具,因为此容器唯一要做的就是提供网页服务。


一个Docker容器只有运行一个进程。有几种方法可以指定它。 Docker 文件 CMD 是默认设置,但可以通过 Compose command: 或在 docker run 图像名称后添加命令来覆盖它。这意味着,如果您 docker run --rm -it your-image /bin/bash,交互式 shell 运行s 而不是 Docker 文件中的 CMD .

这里最简单的答案就是不用担心 运行 交互式 shell。 docker run 没有命令的图像。 docker exec 谨慎;它是一个非常有用的调试工具,但通常不是您与容器交互的主要方式。

# do not override the command at the end
docker run -d -p 8080:80 nginx-custom:1.21.1

一个Docker容器只有运行一个进程。当该过程完成时,容器退出。这意味着主容器进程需要是一个 long-运行ning 的前台进程;它不能是启动后台进程然后完成的脚本,也不能是“服务”类型的命令。

基础 nginx 图像会显示类似

的内容
CMD ["nginx", "-g", "daemon off;"]

它将 Nginx 服务器作为前台进程启动。

如果你真的需要run supervisord,那么主要CMD需要运行 supervisord而不是service 命令,它需要一个 -n 选项来 运行 它在前台。如果您使用 CMD 的 JSON 数组形式,那么您有责任自己将命令分解为单词。如果有嵌入空格(如我示例中的 daemon off; 或问题中的 CMD ),它们将被视为包含空格的单个单词,就像您在 [=75= 中引用它一样].

CMD ["supervisord", "-n"]

一般来说,像 service 这样的命令在 Docker 中不起作用,原因有几个。由于它们会立即执行某些操作并 return 它们不适合作为主要容器命令。如果您像在问题中那样说“重新启动”,则该服务之前不会 运行ning。如果环境依赖于一些 init 守护进程,那也不会是 运行ning,并且 servicesystemctl 将无法与它对话。不要尝试引入init系统,直接运行命令作为单个前台主容器进程