在Docker容器启动时运行多个命令

3
我有一个基于Ubuntu 16.04的简单Docker镜像,基于Dockerfile,CMD是"/sbin/ejabberdctl foreground"。为了保持Docker容器启动后的存活状态,我以前会在前台运行ejabberd服务器。但是,在启动容器和/sbin/ejabberdctl之后,我需要执行另一个命令(例如ejabberdctl list_cluster)。尝试将两个命令添加到bash脚本中,但不起作用。尝试运行/sbin/ejbberdctl start &,也不起作用。应该如何解决?
2个回答

2

选项A: 创建一个简单的bash脚本,运行容器并列出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"

enter image description here 选项B

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

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

我会建议使用官方的alpine ejabberd镜像,它仅有30MB,而不是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"]

现在创建管理者配置文件。
[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。请注意,此处使用了 join cluster 参数以加入集群(如果需要)。如果不需要加入集群,请将其删除。
[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

enter image description here


感谢您详细的回答。实际上,您说得对,我对自动聚类很感兴趣,因此一旦 ejabberd 成员容器启动,它必须加入到预定义的根节点中,该节点由环境变量指定。这里的重点是,我没有使用 ejabberd 的官方镜像,因为它不符合我的需求。我有自己的 ejabberd 镜像,并且在 Kubernetes 中使用它来运行 ejabberd 集群。如果我根据您的答案对自己的 ejabberd 镜像进行所有适当的更改,您认为这在 Kubernetes 中也能够工作吗? - Ahnenerbe
ejabberd镜像是平台无关的,因此无论您想在哪里运行,其行为都将保持不变。 - Adiii
一旦运行ejabberd join_cluster命令,我会收到有关mnesia db的错误。不幸的是,目前我无法重现该错误(不知道为什么这个错误现在消失了),但情况仍然相同,除了这个错误日志之外没有其他错误日志: - Ahnenerbe
我同意你的观点,但是在官方的18.06镜像中没有启用Riak的选项。我进行了分支并进行了更改以启用Riak,但遇到了其他问题,并且没有得到他们的支持。因此,我创建了自己的镜像,在supervisord添加之前一切正常运行。我的意思是容器在Kubernetes中正确运行,主要问题是join_cluster是手动的,但可以工作。使用您的配置,在docker环境中完美地工作(我在同一网络中运行2个容器-一个根容器具有静态主机名,另一个成员容器具有生成的主机名)。成员自动连接到根容器。 - Ahnenerbe
1
谢谢。我会尝试解决这个问题并在这里更新。 - Ahnenerbe
显示剩余13条评论

0
你正在寻找的东西叫做supervisord。在官方Docker文档中,你可以找到如何使用它的一些示例。
请注意,除非绝对必要,否则不建议在同一个容器中运行多个服务。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接