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

时间:2022-10-09 17:01:49

I've seen lots of examples of making Docker containers for Rails applications. Typically they run a rails server and have a CMD that runs migrations/setup then brings up the Rails server.

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

If I'm spawning 5 of these containers at the same time, how does Rails handle multiple processes trying to initiate the migrations? I can see Rails checking the current schema version in the general query log (it's a MySQL database):

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

 SELECT `schema_migrations`.`version` FROM `schema_migrations`

But I can see a race condition here if this happens at the same time on different Rails instances.

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

Considering that DDL is not transactional in MySQL and I don't see any locks happening in the general query log while running migrations (other than the per-migration transactions), it would seem that kicking them off in parallel would be a bad idea. In fact if I kick this off three times locally I can see two of the rails instances crashing when trying to create a table because it already exists while the third rails instance completes the migrations happily. If this was a migration that inserted something into the database it would be quite unsafe.

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

Is it then a better idea to run a single container that runs migrations/setup then spawns (for example) a Unicorn instance which in turn spawns multiple rails workers?

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

Should I be spawning N rails containers and one 'migration container' that runs the migration then exits?

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

Is there a better option?

有更好的选择吗?

2 个解决方案

#1


24  

Especially with Rails I don't have any experience, but let's look from a docker and software engineering point of view.

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

The Docker team advocates, sometimes quite aggressively, that containers are about shipping applications. In this really great statement, Jerome Petazzoni says that it is all about separation of concerns. I feel that this is exactly the point you already figured out.

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

Running a rails container which starts a migration or setup might be good for initial deployment and probably often required during development. However, when going into production, you really should consider separating the concerns.

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

Thus I would say have one image, which you use to run N rails container and add a tools/migration/setup whatever container, which you use to do administrative tasks. Have a look what the developers from the official rails image say about this:

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

It is designed to be used both as a throw away container (mount your source code and start the container to start your app), as well as the base to build other images off of.

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

When you look at that image there is no setup or migration command. It is totally up to the user how to use it. So when you need to run several containers just go ahead.

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

From my experience with mysql this works fine. You can run a data-only container to host the data, run a container with the mysql server and finally run a container for administrative tasks like backup and restore. For all three containers you can use the same image. Now you are free to access your database from let's say several Wordpress containers. This means clear separation of concerns. When you use docker-compose it is not that difficult to manage all those containers. Certainly there are already many third party containers and tools to also support you with setting up a complex application consisting of several containers.

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

Finally, you should decide whether docker and the micro-service architecture is right for your problem. As outlined in this article there are some reasons against. One of the core problems being that it adds a whole new layer of complexity. However, that is the case with many solutions and I guess you are aware of this and willing to except it.

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

#2


6  

docker run <container name> rake db:migrate

Starts you standard application container but don't run the CMD (rails server), but rake db:migrate

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

UPDATE: Suggested by Roman, the command would now be:

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

docker exec <container> rake db:migrate

#1


24  

Especially with Rails I don't have any experience, but let's look from a docker and software engineering point of view.

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

The Docker team advocates, sometimes quite aggressively, that containers are about shipping applications. In this really great statement, Jerome Petazzoni says that it is all about separation of concerns. I feel that this is exactly the point you already figured out.

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

Running a rails container which starts a migration or setup might be good for initial deployment and probably often required during development. However, when going into production, you really should consider separating the concerns.

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

Thus I would say have one image, which you use to run N rails container and add a tools/migration/setup whatever container, which you use to do administrative tasks. Have a look what the developers from the official rails image say about this:

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

It is designed to be used both as a throw away container (mount your source code and start the container to start your app), as well as the base to build other images off of.

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

When you look at that image there is no setup or migration command. It is totally up to the user how to use it. So when you need to run several containers just go ahead.

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

From my experience with mysql this works fine. You can run a data-only container to host the data, run a container with the mysql server and finally run a container for administrative tasks like backup and restore. For all three containers you can use the same image. Now you are free to access your database from let's say several Wordpress containers. This means clear separation of concerns. When you use docker-compose it is not that difficult to manage all those containers. Certainly there are already many third party containers and tools to also support you with setting up a complex application consisting of several containers.

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

Finally, you should decide whether docker and the micro-service architecture is right for your problem. As outlined in this article there are some reasons against. One of the core problems being that it adds a whole new layer of complexity. However, that is the case with many solutions and I guess you are aware of this and willing to except it.

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

#2


6  

docker run <container name> rake db:migrate

Starts you standard application container but don't run the CMD (rails server), but rake db:migrate

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

UPDATE: Suggested by Roman, the command would now be:

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

docker exec <container> rake db:migrate