如何使一个容器运行多个进程?

作者:taikulawo创建时间:2019-09-21字数统计:3159预计阅读需要8分钟

#云计算

本文翻译自 https://docs.docker.com/config/containers/multi-service_container/

我们都知道,所谓的容器就是一个被隔离到不同环境的进程而已,那我们如果在一个容器内运行多个进程呢?

一个容器的主进程是 ENTRYPOINT 或者在 Dockerfile 最后的 CMD

容器的主进程负责管理它启动的全部进程。

在某些条件下,主进程由于出错而退出,容器退出时,主进程并不能优雅地处理停止的子进程。

如果你的进程会出现上述情况,你启动容器时可以使用 --init 标志,在容器内插入一个简易的初始化进程作为主进程,容器退出时INIT 处理这些停止的子进程 ---- 子进程作为孤儿进程会被托管到 INIT 进程

用上述方式管理容器的生命周期比使用笨重的 sysinit, upstart, 或者 systemd 更优雅

如果需要在一个容器内运行多个服务,你可以通过下面几种不同方式解决。

  • 将全部的命令都封装到脚本中,并将脚本作为 CMD 执行。这是一个非常原生的做法。 比如

    #!/bin/bash
    
    # Start the first process
    ./my_first_process -D
    status=$?
    if [ $status -ne 0 ]; then
      echo "Failed to start my_first_process: $status"
      exit $status
    fi
    
    # Start the second process
    ./my_second_process -D
    status=$?
    if [ $status -ne 0 ]; then
      echo "Failed to start my_second_process: $status"
      exit $status
    fi
    
    # Naive check runs checks once a minute to see if either of the processes exited.
    # This illustrates part of the heavy lifting you need to do if you want to run
    # more than one service in a container. The container exits with an error
    # if it detects that either of the processes has exited.
    # Otherwise it loops forever, waking up every 60 seconds
    
    while sleep 60; do
      ps aux |grep my_first_process |grep -q -v grep
      PROCESS_1_STATUS=$?
      ps aux |grep my_second_process |grep -q -v grep
      PROCESS_2_STATUS=$?
      # If the greps above find anything, they exit with 0 status
      # If they are not both 0, then something is wrong
      if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
        echo "One of the processes has already exited."
        exit 1
      fi
    done

    Dockerfile

    FROM ubuntu:latest
    COPY my_first_process my_first_process
    COPY my_second_process my_second_process
    COPY my_wrapper_script.sh my_wrapper_script.sh
    CMD ./my_wrapper_script.sh
  • 如果你先启动主进程但暂时需要在运行其他的进程(比如与主进程交互),那你可以使用 bash 的任务控制解决。

    #!/bin/bash
    
    # turn on bash's job control
    set -m
    
    # Start the primary process and put it in the background
    ./my_main_process &
    
    # Start the helper process
    ./my_helper_process
    
    # the my_helper_process might need to know how to wait on the
    # primary process to start before it does its work and returns

now we bring the primary process back into the foreground

and leave it there

fg %1

Dockerfile

FROM ubuntu:latest COPY my_main_process my_main_process COPY my_helper_process my_helper_process COPY my_wrapper_script.sh my_wrapper_script.sh CMD ./my_wrapper_script.sh

- 使用一个像 `supervisord` 一样的进程管理器。这是一个重量级的方法,需要将 `supervisord` 和它的配置文件打包到镜像(或者直接使用基于 `supervisord`的镜像),然后启动supervisor,它会根据配置文件代你管理进程,下面是一个使用 supervisord 的 Dockerfill,我们假定已经预先写好了 `supervisord.conf`,`my_first_process`, `my_second_process`,并放到与 `Dockerfile` 同级的目录

FROM ubuntu:latest RUN apt-get update && apt-get install -y supervisor RUN mkdir -p /var/log/supervisor COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf COPY my_first_process my_first_process COPY my_second_process my_second_process CMD "/usr/bin/supervisord"

0 comments
Anonymous
Markdown is supported

Be the first guy leaving a comment!