我已经看过很多为Rails应用程序制作Docker容器的例子。通常,他们运行rails服务器并拥有运行迁移/设置的CMD,然后启动Rails服务器。
如果我同时生成其中5个容器,Rails如何处理尝试启动迁移的多个进程?我可以看到Rails检查通用查询日志中的当前模式版本(它是一个MySQL数据库):
SELECT `schema_migrations`.`version` FROM `schema_migrations`
但如果在不同的Rails实例上同时发生这种情况,我可以看到竞争条件。
考虑到DDL在MySQL中不是事务性的,并且我在运行迁移时(通过每次迁移事务除外)看不到通用查询日志中发生的任何锁定,看起来并行将它们踢掉是个坏主意。事实上,如果我在本地启动三次,我可以看到两个rails实例在尝试创建表时崩溃,因为它已经存在,而第三个rails实例很快就完成了迁移。如果这是一个将某些东西插入数据库的迁移,那将非常不安全。
然后运行一个运行迁移/设置的单个容器然后产生(例如)一个Unicorn实例然后生成多个rails工作人员会更好吗?
我是否应该生产N个铁轨容器和一个迁移容器'运行迁移然后退出?
有更好的选择吗?
答案 0 :(得分:24)
特别是对于Rails,我没有任何经验,但让我们从码头工人和软件工程的角度来看。
Docker团队主张(有时候非常积极地)容器是关于运送应用程序的。在this really great statement中,杰罗姆·佩塔佐尼(Jerome Petazzoni)说这完全是关于分离问题。我觉得这正是你已经想到的一点。
运行启动迁移或设置的rails容器可能适合初始部署,并且可能在开发期间经常需要。但是,在投入生产时,你真的应该考虑分离问题。
因此,我想说有一个图像,用于运行N rails容器并添加工具/迁移/设置任何容器,用于执行管理任务。看看official rails image的开发人员对此的看法:
它既可以用作丢弃容器(安装源代码并启动容器来启动应用程序),也可以用来构建其他图像。
当您查看该图像时,没有设置或迁移命令。这完全取决于用户如何使用它。因此,当您需要运行多个容器时,请继续。
根据我对 mysql 的经验,这很好用。您可以运行仅数据容器来托管数据,使用mysql服务器运行容器,最后运行容器以执行备份和还原等管理任务。对于所有三个容器,您可以使用相同的图像。现在您可以自由访问您的数据库,让我们说几个 Wordpress 容器。这意味着明确分离关注点。当您使用docker-compose
时,管理所有这些容器并不困难。当然,已经有许多第三方容器和工具也可以帮助您设置由多个容器组成的复杂应用程序。
最后,您应该确定 docker 和微服务架构是否适合您的问题。正如this article中所述,有一些理由反对。其中一个核心问题是它增加了一层全新的复杂性。然而,许多解决方案就是这种情况,我想你已经意识到这一点,并愿意除此之外。
答案 1 :(得分:6)
docker run <container name> rake db:migrate
启动标准应用程序容器但不运行CMD(rails server
),但rake db:migrate
更新:罗马建议,命令现在为:
docker exec <container> rake db:migrate