Exécuter rake assets:precompile sans base de données

J’ai remarqué que la tâche rake assets:precompile nécessite une connexion à la base de données : cela signifie que cette tâche ne peut être exécutée qu’au moment de l’exécution (après le déploiement) et non au moment de la construction (lors de la création de l’image du conteneur). Étant donné que cette tâche est très coûteuse en termes de temps d’exécution, cela peut être gênant.

N’étant pas développeur Ruby/Rails, j’ai effectué quelques recherches et découvert que ce comportement pouvait être désactivé jusqu’à Rails 4, et que par la suite, les développeurs ont eu recours à des astuces (connexion nulle à la base de données). Cette dernière méthode nécessite bien sûr une connaissance approfondie de l’application afin d’éviter toute rupture de fonctionnement.

En cherchant une meilleure solution, j’ai trouvé ce commit qui semble similaire dans son esprit. Mes questions sont donc les suivantes :

  • les développeurs travaillent-ils déjà sur ce sujet, ou y a-t-il des raisons techniques qui empêchent de le faire ?
  • si certaines parties de la tâche nécessitent effectivement une connexion à la base de données, serait-il possible de diviser la tâche en deux (ou plus), afin que certaines opérations (par exemple la compilation des fichiers de localisation, la minification du JavaScript et du CSS) puissent être effectuées au moment de la construction ?
  • existe-t-il actuellement une solution de contournement connue (par exemple une « base de données nulle » comme mentionné ci-dessus) ?

Nous stockons les thèmes dans la base de données (ils sont édités dans l’interface d’administration), donc le CSS est contenu dans PostgreSQL. Vous avez donc besoin de la connexion à la base de données au moment de la construction pour pouvoir précompiler ces éléments.

Merci pour ces informations !

Serait-il envisageable d’implémenter la construction des locales séparément (à exécuter au moment de la construction) ?
De plus, je peux imaginer que certains environnements (c’est le cas pour moi, du moins) pourraient ne pas souhaiter autoriser la modification des thèmes : serait-il possible de prévoir un stockage alternatif pour le CSS dans ce cas ?

Nous avons bien évoqué l’idée d’un interrupteur permettant de désactiver entièrement l’interface de personnalisation, ce qui permettrait de compiler les fichiers CSS lors de la phase de construction et de les télécharger vers un stockage objet pendant cette même phase (c’est-à-dire comme pour le cœur JS et les plugins).

Cependant, il s’agit d’un cas très spécifique, qui ne concernerait que des déploiements de type entreprise, sans apporter la moindre valeur à 99 % des communautés en ligne. Cela ne figure donc pas dans notre feuille de route, et il serait difficile de justifier de consacrer des efforts à cette fonctionnalité plutôt qu’au développement de nouvelles fonctionnalités ou à l’optimisation des performances.

Pourriez-vous nous en dire plus sur votre environnement et votre cas d’utilisation ?

C’est bon de savoir que l’idée a déjà été discutée. Je comprends que l’ampleur du travail nécessaire pour ce changement soit probablement trop importante pour être justifiée.

Dans mon cas, Discourse sera associé à un site web préexistant, il y aura donc un thème personnalisé fixe pour correspondre à celui du site web : cela n’aurait pas de sens de le changer dynamiquement.

Oh, je voulais dire le cas d’usage où vous ne pouvez pas vous connecter à la base de données au moment de la « compilation ».

Ah bon : eh bien, lorsque je construis l’image, je travaille sur mon ordinateur portable de développement. L’image est ensuite poussée vers un référentiel, et le système final (VPS chez DigitalOcean) la récupère depuis là.

La base de données réside dans un volume sur le VPS, elle ne peut donc pas être mise à jour depuis mon ordinateur portable : cela nécessiterait d’arrêter Discourse, de synchroniser la base de données vers mon ordinateur portable via rsync, de construire et de pousser l’image, et enfin de redémarrer Discourse…

Donc vous exécutez la base de données et l’application toutes les deux dans un seul droplet ?

Dans ce cas, suivre notre guide d’installation officiel, qui aboutit à un droplet contenant à la fois l’application et la base de données, vous permettra d’obtenir un site entièrement fonctionnel, pouvant être mis à jour via l’interface web et, optionnellement, en ligne de commande avec une reconstruction complète de l’image.

Si par là vous entendez « directement sur l’hôte », alors non. Elles s’exécutent dans un conteneur, plus précisément un conteneur podman. Idéalement, je scinderais ce conteneur en plusieurs autres (un pour Discourse, un pour PostgreSQL, un pour Redis…), mais cela se rattache au problème que nous discutons, je suis donc encore indécis quant à la meilleure démarche à suivre.

Cela me semble peu sûr. En général, je teste les conteneurs dans mon environnement de développement avant de les déployer en production. De plus, idéalement, les conteneurs devraient être en lecture seule.

Vous pouvez séparer ces conteneurs, puis lancer le processus d’initialisation de l’image dans une autre droplet éphémère. Comme les droplets sont facturés à l’heure, cela restera peu coûteux. Vous pouvez même exploiter le réseau privé des droplets entre l’hôte du conteneur de base de données et l’hôte du conteneur de « construction ».

Haha, merci pour l’idée, mais cela commence à devenir compliqué. De plus, cela ne résoudra pas le problème, car nous devrons toujours arrêter Discourse et attendre le processus de bootstrap, sinon les données pourraient être incohérentes.

Il semble que nous devrons accepter un temps d’arrêt prolongé (5 à 6 minutes pour la migration et la précompilation) lors des mises à niveau. Cependant, je vous serais reconnaissant de bien vouloir créer un problème de priorité faible dans le suivi, peut-être avec un lien vers ce sujet.

Merci et continuez ce bon travail !

Non, ce n’est pas le cas.

Il ne devrait s’agir que de « quelques secondes » plutôt que de 5 à 6 minutes, mais vous aurez besoin de conteneurs de données et web dédiés. Cela dépend de ce que vous souhaitez privilégier.

Par ailleurs, selon les tests de référence, la reconstruction sur un serveur rapide devrait prendre environ 3 minutes.

C’est bon à savoir, merci. Dans ce cas, je vais certainement séparer les conteneurs, ce qui est de toute façon une meilleure architecture.

Cependant, je ne vois pas en quoi cela fait une différence ? Si je ne me trompe pas, tous les conteneurs partagent tous les CPU de l’hôte (sauf configuration différente), donc les processus devraient s’exécuter en parallèle dans les deux cas. Est-ce que je manque quelque chose ?

Votre ancien conteneur continuera de fonctionner pendant que le nouveau sera en cours de démarrage. Ensuite, vous pourrez rapidement désactiver l’ancien et démarrer le nouveau, ce qui réduira les temps d’arrêt.