【问题标题】:Run a service automatically in a docker container在 docker 容器中自动运行服务
【发布时间】:2018-03-22 16:28:10
【问题描述】:

我正在设置一个简单的图像:一个包含 Riak(一个 NoSQL 数据库)的图像。该映像以riak start 作为 CMD 启动 Riak 服务。现在,如果我使用docker run -d quintenk/riak-dev 作为守护进程运行它,它会启动Riak 进程(我可以在日志中看到)。但是,它会在几秒钟后自动关闭。如果我使用docker run -i -t quintenk/riak-dev /bin/bash 运行它,则不会启动 riak 进程(更新:请参阅答案以获得对此的解释)。事实上,根本没有任何服务在运行。我可以使用终端手动启动它,但我希望 Riak 自动启动。我认为其他服务也会发生这种行为,Riak 只是一个例子。

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


作为参考,这里是可以用来创建图像的 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 根据 sesm 他的评论在 CMD 中更改为 -F


我自己的答案

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

【问题讨论】:

  • 顺便说一句。我现在(出于开发目的)通过启动容器、附加到它,然后启动 Riak 命令行来使用容器。

标签: riak docker


【解决方案1】:

要保持 docker 容器运行,您需要在前台保持一个进程处于活动状态。

因此,您可以将 Dockerfile 中的最后一行替换为

CMD /bin/riak console

甚至

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

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

【讨论】:

  • 我现在使用第二个选项。感谢您的反馈!
【解决方案2】:

使用 tail 保持容器存活是一种 hack。另外请注意,使用-f 选项的容器将在日志轮换发生时终止(这可以通过使用-F 来避免)。

更好的解决方案是使用supervisor。看看这个tutorial 关于在 Docker 容器中运行 Riak。

【讨论】:

  • 这看起来很有希望。如果您已经有将它与 docker 结合使用的经验,您愿意在这里分享一个简短的示例吗?
【解决方案3】:

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

听起来您只想在附加到容器时能够监控日志。我的用例有点不同,我希望命令自动启动,但我希望能够附加到容器并位于 bash shell 中。我能够解决我们的两个问题,如下所示:

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

在您的情况下,只需添加行 /bin/riak start &amp;&amp; tail -F /var/log/riak/erlang.log.1,或根据所需的功能将 /bin/riak starttail -F /var/log/riak/erlang.log.1 放在不同的行上。

现在将您的更改提交到您的容器,并使用:docker run -i -t quintenk/riak-dev /bin/bash 再次运行它。你会发现你在 bashrc 中的命令在你附加的时候已经在运行了。

【讨论】:

  • 这实际上是一个非常好的解决方案 :) 请注意,0.6.5 添加了 docker run -a 选项以实现主管兼容性。您可能也想解决这个问题。
  • 不是一个好的解决方案。进程退出怎么办,tailf继续运行,容器不退出。
  • @MincăDanielAndrei 你说的有一部分是对的。这不是一个生产就绪的解决方案,由于您提到的原因,它是不可持续的。最好让图像的entrypointcmd 成为您要运行的进程本身。这通常意味着您需要为所述进程找到--no-daemon 选项,以防止容器在入口点自身背景并退出时退出,并使其记录到stderr/stdout。
  • 另一种选择是使用 dumb-init ,容器的初始化系统,如此处所述 engineeringblog.yelp.com/2016/01/…
【解决方案4】:

解释:

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

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

通过在 Buildfile 中使用 CMD /bin/riak start &amp;&amp; tail -f /var/log/riak/erlang.log.1,您可以使用 docker run -d {image} 将容器作为后台进程启动,这就像一个魅力。

【讨论】:

  • 同样,我正在尝试对 CDH 进行 dockerize。在这种情况下,我正在使用 RUN 命令启动服务。它在该 RUN 命令之后启动并退出。可能是什么原因?
  • @GopsAB 可能存在某种错误,导致主进程无法(保持)运行。检查您的日志或通过使用 /bin/bash 启动容器来手动尝试您的 CMD,看看会发生什么
  • 如果进程崩溃,tailf 会继续运行。与@damick 相同的故事
【解决方案5】:

因为我想要一种干净的方式让进程稍后退出,所以我将最后一个命令调用 shell 的 read,这会导致该进程阻塞,直到我稍后附加到它并按 Enter .

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 更复杂的脚本。

【讨论】:

    【解决方案6】:

    每当我开始构建一个新的 docker 容器时,我都会使用一个简单的技巧。为了让它保持活力,我在入口点脚本中使用了 ping。

    所以在 Dockerfile 中,例如,当使用 debian 时,我确保我可以 ping。 顺便说一句,检查容器内可以访问的内容总是很好。

    ...
    RUN DEBIAN_FRONTEND=noninteractive apt-get update \
     && apt-get install -y iputils-ping 
    ...
    ENTRYPOINT ["entrypoint.sh"]
    

    并且在 entrypoint.sh 文件中

    #!/bin/bash
    ...
    ping 10.10.0.1 >/dev/null 2>/dev/null
    

    我使用它而不是 CMD bash,因为我总是使用启动文件结束。

    【讨论】:

      猜你喜欢
      • 2014-09-27
      • 2013-08-05
      • 2018-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-18
      • 2021-02-26
      • 1970-01-01
      相关资源
      最近更新 更多