如果服务在 docker 构建期间启动,它应该在运行时 运行 吗?

If a service is started during docker build, should it be running at runtime?

我一直致力于在单个容器中设置自包含的 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 在运行时没有启动?

My intuition says that if mysql is started during the build, it should be available at runtime

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

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

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

最终,您将了解 Docker 的强大之处在于如何真正打破 MySQL 和 Rails 应用程序容器以及 运行它在 an entirely different container 中链接在一起。

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

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

或者像您一样通过调用单个脚本。

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