web-dev-qa-db-fra.com

Exécution de migrations avec Rails dans un conteneur Docker avec plusieurs instances de conteneur

J'ai vu de nombreux exemples de création de conteneurs Docker pour les applications Rails. En général, ils exécutent un serveur Rails et ont un CMD qui exécute les migrations/configuration, puis apporte le serveur Rails.

Si je génère 5 de ces conteneurs en même temps, comment Rails gère-t-il plusieurs processus essayant d'initier les migrations? Je peux voir Rails vérifier la version actuelle du schéma dans le journal général des requêtes (il s'agit d'une base de données MySQL):

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

Mais je peux voir une condition de concurrence ici si cela se produit en même temps sur différentes instances Rails.

Étant donné que DDL n'est pas transactionnel dans MySQL et que je ne vois aucun verrou se produire dans le journal général des requêtes lors de l'exécution des migrations (autres que les transactions par migration), il semblerait que les lancer en parallèle soit une mauvaise idée. En fait, si je lance cela trois fois localement, je peux voir deux des instances Rails planter lors de la tentative de création d'une table car elle existe déjà tandis que la troisième Rails = l'instance termine les migrations avec bonheur. S'il s'agissait d'une migration qui insérait quelque chose dans la base de données, ce serait assez dangereux.

Est-ce alors une meilleure idée d'exécuter un seul conteneur qui exécute les migrations/configuration puis génère (par exemple) une instance Unicorn qui génère à son tour plusieurs Rails travailleurs?

Dois-je générer N Rails conteneurs et un "conteneur de migration" qui exécute la migration puis se termine?

Y a-t-il une meilleure option?

30
Martin Foot

Surtout avec Rails Je n'ai aucune expérience, mais regardons d'un point de vue docker et génie logiciel.

L'équipe Docker préconise, parfois de manière assez agressive, que les conteneurs concernent les applications d'expédition. Dans cette très bonne déclaration , Jérôme Petazzoni dit qu'il s'agit de séparation des préoccupations. Je pense que c'est exactement le point que vous avez déjà compris.

L'exécution d'un conteneur Rails qui démarre une migration ou une configuration peut être bonne pour le déploiement initial et probablement souvent nécessaire pendant le développement. Cependant, lors de la mise en production, vous devriez vraiment envisager de séparer les problèmes.

Ainsi, je dirais avoir une image, que vous utilisez pour exécuter N Rails conteneur et ajouter un outil/migration/configuration quel que soit le conteneur, que vous utilisez pour effectuer des tâches administratives. Jetez un œil à ce que les développeurs à partir de officiel Rails image dire à ce sujet:

Il est conçu pour être utilisé à la fois comme conteneur à jeter (montez votre code source et démarrez le conteneur pour démarrer votre application), ainsi que comme base pour construire d'autres images à partir de.

Lorsque vous regardez cette image, il n'y a aucune commande de configuration ou de migration. Il appartient entièrement à l'utilisateur de l'utiliser. Donc, lorsque vous devez exécuter plusieurs conteneurs, allez-y.

D'après mon expérience avec mysql cela fonctionne très bien. Vous pouvez exécuter un conteneur de données uniquement pour héberger les données, exécuter un conteneur avec le serveur mysql et enfin exécuter un conteneur pour les tâches administratives telles que la sauvegarde et la restauration. Pour les trois conteneurs, vous pouvez utiliser la même image. Vous êtes maintenant libre d'accéder à votre base de données à partir de disons plusieurs conteneurs Wordpress . Cela signifie une séparation claire des préoccupations. Lorsque vous utilisez docker-compose ce n'est pas si difficile de gérer tous ces conteneurs. Certes, il existe déjà de nombreux conteneurs et outils tiers pour vous aider également à configurer une application complexe composée de plusieurs conteneurs.

Enfin, vous devez décider si docker et l'architecture de micro-service sont adapté à votre problème. Comme indiqué dans cet article il y a quelques raisons contre. L'un des principaux problèmes est qu'il ajoute une toute nouvelle couche de complexité. Cependant, c'est le cas avec de nombreuses solutions et je suppose que vous en êtes conscient et que vous êtes prêt à l'exclure.

26
Jan Suchotzki
docker run <container name> rake db:migrate

Démarre votre conteneur d'applications standard mais n'exécute pas le CMD (Rails server), mais rake db:migrate

PDATE: Suggérée par Roman, la commande serait désormais:

docker exec <container> rake db:migrate
6
Timo Schilling