在具有多个容器实例的Docker容器中使用Rails运行迁移

Mar*_*oot 30 mysql ruby-on-rails database-migration rails-migrations docker

我已经看到很多为Rails应用程序制作Docker容器的例子.通常,他们运行rails服务器并拥有运行迁移/设置的CMD,然后启动Rails服务器.

如果我同时生成其中5个容器,Rails如何处理尝试启动迁移的多个进程?我可以看到Rails检查通用查询日志中的当前模式版本(它是一个MySQL数据库):

 SELECT `schema_migrations`.`version` FROM `schema_migrations`
Run Code Online (Sandbox Code Playgroud)

但是如果在不同的Rails实例上同时发生这种情况,我可以看到竞争条件.

考虑到DDL在MySQL中不是事务性的,并且我在运行迁移时看不到通用查询日志中发生任何锁定(除了每次迁移事务),看起来并行启动它们是个坏主意.事实上,如果我在本地启动三次,我可以看到两个rails实例在尝试创建表时崩溃,因为它已经存在,而第三个rails实例很快就完成了迁移.如果这是一个将某些东西插入数据库的迁移,那将是非常不安全的.

那么运行一个运行迁移/设置的单个容器然后产生(例如)一个Unicorn实例然后生成多个rails工作人员会更好吗?

我是否应该产生N个轨道容器和一个运行迁移的"迁移容器"然后退出?

有更好的选择吗?

Jan*_*zki 27

特别是对于Rails,我没有任何经验,但让我们从码头工人和软件工程的角度来看.

Docker团队主张(有时候非常积极地)容器是关于运输应用程序的.在这个非常好的声明中,杰罗姆·佩塔佐尼说,这完全是关于分离问题.我觉得这正是你已经想到的一点.

运行启动迁移或设置的rails容器可能适合初始部署,并且可能在开发期间经常需要.但是,在投入生产时,您应该考虑将问题分开.

因此,我想说有一个图像,用于运行N rails容器并添加工具/迁移/设置任何容器,用于执行管理任务.看看官方rails图像的开发人员对此有何看法:

它被设计为既可以用作丢弃容器(安装源代码并启动容器来启动应用程序),也可以用作构建其他图像的基础.

查看该图像时,没有设置或迁移命令.这完全取决于用户如何使用它.因此,当您需要运行多个容器时,请继续.

根据我对mysql的经验,这很好用.您可以运行仅数据容器来托管数据,使用mysql服务器运行容器,最后运行容器以执行备份和还原等管理任务.对于所有三个容器,您可以使用相同的图像.现在您可以自由地访问您的数据库,比如说几个Wordpress容器.这意味着明确分离关注点.当您使用docker-compose它时,管理所有这些容器并不困难.当然,已经有许多第三方容器和工具可以支持您设置由多个容器组成的复杂应用程序.

最后,您应该确定docker微服务架构是否适合您的问题.如本文所述,有一些原因可以解决.其中一个核心问题是它增加了一层全新的复杂性.然而,许多解决方案就是这种情况,我想你已经意识到这一点,并愿意除此之外.


Tim*_*ing 6

docker run <container name> rake db:migrate
Run Code Online (Sandbox Code Playgroud)

启动标准应用程序容器但不运行CMD(rails server),但是rake db:migrate

更新:罗马建议,命令现在是:

docker exec <container> rake db:migrate
Run Code Online (Sandbox Code Playgroud)

  • 如果我没弄错的话,exec会在已经运行的容器中执行命令.因此,您必须在没有迁移的情况下启动应用程序容器,并在以后应用迁移.这可能会导致问题.首先应用迁移(通过运行)并在之后启动应用程序容器会更加清晰.Docker组合可能对此有所帮助. (4认同)