【问题标题】:run multiple commands in docker container start在 docker 容器启动中运行多个命令
【发布时间】:2019-03-11 10:22:58
【问题描述】:

我有一个在 ubuntu 16.04 上运行的简单 docker 映像,它基于 CMD 为 "/sbin/ejabberdctl foreground" 的 dockerfile。为了让 docker 容器在启动后保持活动状态,我曾经在前台运行 ejabberd 服务器。然而,在启动容器和/sbin/ejabberdctl 之后,一旦 ejabberdctl 已经运行(例如ejabberdctl list_cluster),我需要执行另一个命令。 尝试将这两个命令添加到 bash 脚本,但它不起作用。试图运行/sbin/ejbberdctl start &,它也没有工作。 用什么方法挖?

【问题讨论】:

    标签: docker ubuntu ejabberd


    【解决方案1】:

    选项 A: 创建一个简单的 bash 脚本来运行容器和 list_cluster 而不修改 ejabberd docker 映像的入口点。

    #!/bin/bash
    if [ "${1}" = "remove_old" ]; then
        echo "removing old ejabberd container"
        docker rm -f ejabberd
    fi
        docker run --rm --name ejabberd -d -p 5222:5222 ejabberd/ecs
        sleep 5
        echo -e "*******list_cluster******"
        docker exec -it ejabberd ash -c "/home/ejabberd/bin/ejabberdctl list_cluster"
    

    选项 B

    在选项 B 中,您需要修改 ejabberd 官方镜像入口点,因为它不允许您在启动时运行多个脚本。因此,在启动时添加您的脚本,同时进行一些修改。

    https://github.com/processone/docker-ejabberd/blob/master/ecs/Dockerfile

    我建议使用 ejabberd 的 仅 30 MB 的官方 alpine 映像,而不是 Ubuntu。 https://hub.docker.com/r/ejabberd/ecs/

    这里的演示也可以针对 Ubuntu 进行修改,但这是针对 alpine ejabberd 官方映像进行测试的。

    如果您对集群感兴趣,请使用 ejabberd 官方镜像 作为 基础镜像ENV MASTER_NODE=ejabberd@ec2-10.0.0.1 用于主节点。

    From ejabberd/ecs:latest
    USER root
    RUN whoami
    COPY supervisord.conf  /etc/supervisord.conf
    RUN apk add supervisor
    RUN mkdir -p /etc/supervisord.d 
    COPY pm2.conf  /etc/supervisord.d/ejabberd.conf
    COPY start.sh  /opt/ejabberd/start.sh
    RUN chmod +x /opt/ejabberd/start.sh
    ENV MASTER_NODE=ejabberd@ec2-10.0.0.1
    ENTRYPOINT ["supervisord", "--nodaemon", "--configuration", "/etc/supervisord.conf"]
    

    现在创建supervisors config文件

    [unix_http_server]
    file = /tmp/supervisor.sock
    chmod = 0777
    chown= nobody:nogroup
    
    [supervisord]
    logfile = /tmp/supervisord.log
    logfile_maxbytes = 50MB
    logfile_backups=10
    loglevel = info
    pidfile = /tmp/supervisord.pid
    nodaemon = true
    umask = 022
    identifier = supervisor
    
    [supervisorctl]
    serverurl = unix:///tmp/supervisor.sock
    
    [rpcinterface:supervisor]
    supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
    
    [include]
    files = /etc/supervisord.d/*.conf
    

    现在创建 ejabberd.conf 以使用 supervisorsd 启动 ejabberd。注意这里加入集群参数用于加入集群,如果你想加入集群。如果不需要,请将其删除。

    [supervisord]
    nodaemon=true
    [program:list_cluster]
    command: /opt/ejabberd/start.sh join_cluster
    stdout_logfile=/dev/stdout
    stdout_logfile_maxbytes=0
    
    [program:ejabberd]
    command=/home/ejabberd/bin/ejabberdctl foreground
    autostart=true
    priority=1
    autorestart=true
    username=ejabberd
    exitcodes=0 , 4
    

    一个/opt/ejabberd/start.sh bash 脚本,一旦 ejabberd 启动,它将list_cluster,如果在调用脚本时传递了参数,它也能够join_cluster

    #!/bin/sh
    until nc -vzw 2 localhost 5222; do sleep 2 ;echo -e "Ejabberd is booting....."; done
    
    if [ $? -eq 0 ]; then
    
    ########## Once ejabberd is up then list the cluster ##########
        echo -e "***************List_Cluster start***********" 
        /home/ejabberd/bin/ejabberdctl list_cluster
        echo -e "***************List_Cluster End***********" 
    ########## If you want to join cluster once up as pass the master node as ENV then pass first param like join_cluster ##########
        if [ "${1}" == "join_cluster" ]; then
        echo -e "***************Joining_Cluster start***********" 
        /home/ejabberd/bin/ejabberdctl join_cluster ejabberd@$MASTER_NODE
        echo -e "***************Joining_Cluster End***********" 
        fi
    else
        echo -e "**********Ejabberd  is down************";
    fi
    

    运行 docker 容器

    docker build -t ejabberd .
    docker run --name ejabberd --rm -it ejabberd
    

    【讨论】:

    • 感谢您的详细解答。实际上你没看错,我对自动集群感兴趣,所以一旦 ejabberd 成员容器启动,它必须加入到由 env 变量预定义的给定根节点。这里的要点是我没有使用 ejabberd 的官方图像,因为它不符合我的需要。我有自己的 ejabberd 映像,我正在使用它在 kubernetes 中运行 ejabberd 集群。如果我根据您的回答对自己的 ejabberd 映像进行所有适当的更改,您认为这也适用于 kubernetes 吗?
    • 我认为没有。您不需要任何特殊更改,只有根节点 docker 不需要加入任何集群,其余的将加入 env 中的根节点传递。对于 ubuntu,您需要更改 ejabberd 的路径,或者可能需要将 #!/bin/sh 更改为 #!/bin/bash 就是这样
    • ejabberd 图像独立于平台,因此无论您想在哪里运行,行为都将保持不变。
    • 感谢您的回复,将尝试使用此并在此处更新
    • 谢谢。将尝试解决该问题并在此处更新
    【解决方案2】:

    您正在搜索的内容称为supervisord。在official docker documentation,您可以找到一些如何使用它的示例。

    请注意,除非绝对必要,否则不鼓励在同一个容器中运行多个服务。

    【讨论】:

      猜你喜欢
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多