如果一个服务在docker build期间启动,它应该在运行时运行吗?

我一直在努力在单个容器中设置一个独立的导轨应用程序。 这意味着同时在一个容器中同时运行rails和数据持久性服务。 在我们的例子中,这意味着MySQL。

但是,我遇到了多个问题得到这个工作,因为MySQL没有运行。

在构build步骤中,如果我RUN mysqld ,然后单独RUN rake db:create step,则rake将会崩溃,因为mysql已closures。

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

我的直觉说,如果在构build期间启动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?

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

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

你的解决scheme是使用服务器启动脚本,或继续调用mysqld_safe就像在CMD行中一样。

一个好主意是使用supervisord将所有服务保持在非守护模式下。 Phusion还通过一个runit初始化脚本提供了一个很好的基础映像 。

最后,您将会了解Docker的强大function在于如何将MySQL从Rails应用程序容器中分离出来,并将其运行在完全不同的容器中 。

RUN命令用于configuration图像,每次调用时都会创build一个新的图层,其中包含运行命令的结果。 因此,如果您需要在映像构build步骤中configuration数据库,则有两种解决scheme:您可以在单个RUN调用中调用多个命令,如

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

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

在这两种情况下,你都必须明白,事实上,你在映像构build过程中运行了某些东西,它不会在容器启动时自动运行。 所以,你必须在容器启动时手动启动你的数据库服务器。