如果在docker build期间启动了服务,它是否应该在运行时运行?

时间:2015-10-23 18:28:35

标签: mysql ruby-on-rails docker debian

我一直在努力在一个容器中设置一个自包含的rails应用程序。这意味着在一个容器中同时运行rails和数据持久性服务。在我们的例子中,这意味着mysql。

但是,我遇到了多个问题,因为mysql没有运行。

在构建步骤中,如果我有RUN mysqld然后单独的RUN rake db:create步骤,则rake会崩溃,因为mysql已关闭。

所以我通过将两个命令包装到脚本中来解决这个问题。但是,在运行时,rails无法启动,因为mysql没有运行。

我的直觉说如果mysql在构建期间启动,它应该在运行时可用,但我没有那种经验。启动rails服务器必须包含在一个脚本中,并再次调用mysqld

这是dockerfile:

FROM ruby:2.2
RUN mkdir -p $APPDIR
WORKDIR $APPDIR
ADD Gemfile* $APPDIR/
RUN bundle install
RUN apt-get update -qq
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y -qq nodejs mysql-server --no-install-recommends
RUN rm -rf /var/lib/apt/lists/* # */ broken syntax highlighting
COPY . $APPDIR
RUN script/mysql-setup.sh # contents are: mysqld_safe; rake db:create; rake db:migrate
EXPOSE 3000
CMD ["script/rails-launcher.sh"] # contents are: mysqld_safe; rails s

我需要在Dockerfile中做一些不同的事情吗?为什么mysql在运行时没有启动?

2 个答案:

答案 0 :(得分:4)

  

我的直觉说如果在构建期间启动mysql,它应该在运行时可用

这是不正确的。 Docker将为您启动服务并执行您在同一RUN命令中定义的后续步骤,但随后它会将所有内容捆绑到后续命令的中间映像中。该映像没有已知的正在运行的进程状态,只有启动所需的任何内容,例如init.d脚本。

您的解决方案将是use a server startup script或继续像mysqld_safe行一样调用CMD

一个好主意是使用supervisord以非守护进程模式维护所有服务。 Phusion also provides a nice base image带有runit初始化程序脚本。

最后,您将看到Docker的强大之处在于如何将MySQL从您的Rails应用容器中实际分解并在链接在一起的an entirely different container中运行它。

答案 1 :(得分:1)

RUN命令用于配置图像,每次调用图像时,都会使用run命令的结果创建一个新图层。因此,如果您需要在映像构建步骤中配置数据库,则有2个解决方案:您可以在单个RUN调用中调用多个命令,例如

RUN /bin/bash -c  "mysqld_safe" && "rake db:create" && "rake db:migrate"

或者通过调用单个脚本,就像你一样。

在这两种情况下,你必须理解,事实上,你在图像构建期间运行了一些东西,它不会在容器启动时自动运行。因此,您必须在容器启动时手动启动数据库服务器。