我一直在努力在一个容器中设置一个自包含的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在运行时没有启动?
答案 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"
或者通过调用单个脚本,就像你一样。
在这两种情况下,你必须理解,事实上,你在图像构建期间运行了一些东西,它不会在容器启动时自动运行。因此,您必须在容器启动时手动启动数据库服务器。