在Docker容器中自动运行服务

我正在build立一个简单的图像:一个拥有Riak(一个NoSQL数据库)的图像。 图像riak start作为一个CMD riak start Riak服务。 现在,如果我使用docker run -d quintenk/riak-dev作为守护进程运行它,它确实启动了Riak进程(我可以在日志中看到)。 但是,几秒钟后会自动closures。 如果我使用docker run -i -t quintenk/riak-dev /bin/bash运行它docker run -i -t quintenk/riak-dev /bin/bash riak进程没有启动(更新:请参阅对此的解释的答案)。 事实上,没有服务运行。 我可以使用terminal手动启动,但我想Riak自动启动。 我认为这种行为也会发生在其他服务上,Riak就是一个例子。

所以,运行/重启容器应该会自动启动Riak。 设置这个的正确方法是什么?


作为参考,这里是可以创build图像的Dockerfile(更新:使用所选答案进行更改):

 FROM ubuntu:12.04 RUN apt-get update RUN apt-get install -y openssh-server curl RUN curl http://apt.basho.com/gpg/basho.apt.key | apt-key add - RUN bash -c "echo deb http://apt.basho.com precise main > /etc/apt/sources.list.d/basho.list" RUN apt-get update RUN apt-get -y install riak RUN perl -p -i -e 's/(?<=\{http,\s\[\s\{")127\.0\.0\.1/0.0.0.0/g' /etc/riak/app.config EXPOSE 8098 CMD /bin/riak start && tail -F /var/log/riak/erlang.log.1 

编辑:-f改为-F在CMD按照他的话说


我自己的答案

在使用Docker一段时间后,我发现使用supervisord来调整我的进程的习惯。 如果您想要示例代码,请查看https://github.com/Krijger/docker-cookbooks 。 我使用我的主pipe图像作为我所有其他图像的基础。 我在这里使用主pipe的博客。

为了让Docker容器保持运行,您需要在前台保持活动状态。

所以你可能可以用你的Dockerfilereplace最后一行

 CMD /bin/riak console 

甚至

 CMD /bin/riak start && tail -F /var/log/riak/erlang.log.1 

请注意,您不能有多行CMD语句,只有最后一个运行。

使用尾部保持容器活着是一个黑客。 此外,请注意,使用-f选项容器将在发生日志轮转时终止(可以通过使用-F来避免)。

更好的解决办法是使用主pipe 。 看看这个关于在Docker容器中运行Riak的教程 。

解释:

如果我使用docker run -i -t quintenk/riak-dev /bin/bash运行它docker run -i -t quintenk/riak-dev /bin/bash riak进程未启动

如下。 在Dockerfile中使用CMD实际上与使用docker docker run {image} {command}启动容器的function相同。 正如Gigablah所说的,只有最后一个CMD被使用,所以在这种情况下,写在Dockerfile中的那个被覆盖。

通过在Buildfile中使用CMD /bin/riak start && tail -f /var/log/riak/erlang.log.1 ,您可以使用docker run -d {image}启动容器作为后台进程,其运行方式类似于魅力。

“如果我使用docker运行它运行-i -t quintenk / riak-dev / bin / bash riak进程不启动”

这听起来像你只想在附着到容器时能够监视日志。 我的用例有点不同,我想要命令自动启动,但我想能够附加到容器,并在一个bash shell。 我能够解决我们的两个问题,如下所示:

在映像/容器中,将自动启动的命令添加到/etc/bash.bashrc文件的末尾。

在你的情况下,只需添加行/bin/riak start && tail -F /var/log/riak/erlang.log.1 ,或者把/bin/riak starttail -F /var/log/riak/erlang.log.1取决于所需的function。

现在把你的修改提交到你的容器,然后再运行它: docker run -i -t quintenk/riak-dev /bin/bash 。 你会发现你放在bashrc里的命令已经在运行了。

因为我想要一个干净的方法让程序在稍后退出,所以我把最后一个命令调用到shell的read ,这会导致该进程阻塞,直到我稍后连接到它并敲回车。

 arthur@macro:~/docker$ sudo docker run -d -t -i -v /raid:/raid -p 4040:4040 subsonic /bin/bash -c 'service subsonic start && read -p "waiting"' WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: [8.8.8.8 8.8.4.4] f27229a260c9 arthur@macro:~/docker$ sudo docker ps [sudo] password for arthur: ID IMAGE COMMAND CREATED STATUS PORTS 35f253bdf45a subsonic:latest /bin/bash -c service 2 days ago Up 2 days 4040->4040 arthur@macro:~/docker$ sudo docker attach 35f253bdf45a arthur@macro:~/docker$ sudo docker ps ID IMAGE COMMAND CREATED STATUS PORTS 

正如你所看到的,容器在你连接之后就退出了,并且解锁了读取。 如果您需要进行其他清理工作,例如停止服务和保存日志等,您当然可以使用比read -p更复杂的脚本。