Si vous voulez exécuter une application Rails et sa base de données au Canada, vous avez déjà presque tout l'artéfact de déploiement. Depuis Rails 7.1, rails new inclut par défaut les fichiers liés à Docker dans l'application, et ce Dockerfile est écrit pour la production. Le travail de conteneurisation est donc déjà fait pour vous. Reste à choisir une machine canadienne capable de construire un Dockerfile, à installer PostgreSQL juste à côté, et à bien régler quatre ou cinq paramètres.
Ce guide suit cette démarche sur une machine virtuelle (VM) dédiée à Toronto qui exécute Coolify, ce que fournit MapleDeploy. L'essentiel s'applique à n'importe quel hôte Docker.
Ce que le Dockerfile généré fait déjà
Il vaut la peine de le lire avant d'y toucher, parce qu'on réécrit souvent des parties qui fonctionnent déjà. Dans le gabarit actuel :
- Il est multiétapes. Les outils de compilation et les modules Node restent dans l'étape jetable, et l'image finale s'exécute sous un utilisateur
railsnon privilégié. - Il définit
RAILS_ENV="production"etBUNDLE_WITHOUT="development", vous n'avez donc pas à les passer vous-même. - Il précompile les ressources statiques pendant la construction avec
SECRET_KEY_BASE_DUMMY=1. Votre clé maîtresse n'est pas requise à la construction, seulement à l'exécution. - Depuis Rails 8, la commande
CMDpar défaut lance Thruster devant Puma, pour l'accélération X-Sendfile et la mise en cache des ressources statiques, et l'image expose le port 80 plutôt que 3000. Thruster ne termine le TLS que si vous définissezTLS_DOMAIN: derrière un proxy inverse, il reste en mode HTTP seulement, ce qui est exactement ce qu'il faut ici. - Le point d'entrée exécute
./bin/rails db:preparelorsque la commande du conteneur se termine par./bin/rails server. C'est aussi vrai avec Thruster, puisque./bin/thrust ./bin/rails serverse termine bel et bien par ces deux arguments.
Ce dernier point compte pour la question des migrations, plus bas.
Étape 1 : le serveur et le type de construction
Créez votre serveur, ouvrez Coolify et ajoutez votre dépôt comme nouvelle application. La version générale de cette procédure se trouve dans notre guide pour déployer votre première application ; voici seulement les réponses propres à Rails.
Choisissez Dockerfile comme type de construction, pas Nixpacks. Nixpacks déduit une configuration de construction pour les projets qui n'en fournissent pas, et il le fait bien. Rails fournit déjà un Dockerfile de production écrit pour cet usage : il n'y a donc rien à déduire.
Réglez Ports Exposes à 80. C'est un échec de déploiement Rails fréquent sur une plateforme Docker, parce qu'on suppose habituellement 3000, et que Rails a changé ce port à l'arrivée de Thruster. Si vous avez généré l'application avec --skip-thruster, utilisez plutôt 3000. Vérifiez la ligne EXPOSE de votre propre Dockerfile au lieu de vous fier à l'un ou l'autre chiffre.
Étape 2 : PostgreSQL sur le même serveur
Ajoutez PostgreSQL comme base de données en un clic dans la même instance Coolify. Coolify affiche une valeur Postgres URL (internal) qui se résout sur le réseau Docker du serveur : votre application joint donc la base sans que la connexion ne quitte jamais la machine. Cela signifie aussi une seule région à vérifier au lieu de deux, un argument que nous développons dans où exécuter une base PostgreSQL gérée au Canada.
Collez cette URL dans les variables d'environnement de votre application, sous le nom DATABASE_URL. Rails la fusionne par-dessus config/database.yml plutôt que de remplacer le fichier, et le guide de configuration décrit précisément comment cette fusion se résout.
Vérifiez ensuite un détail souvent oublié. Si vous avez généré une application Rails 8 avec Postgres sans passer --skip-solid, votre bloc de production est une configuration multibase : primary, cache, queue et cable, chacune pointant vers un nom de base distinct. DATABASE_URL ne couvre que la principale. Les connexions non principales lisent leurs propres variables, formées en accolant le nom de la connexion à _DATABASE_URL :
DATABASE_URL=postgres://user:pass@host:5432/app_production
QUEUE_DATABASE_URL=postgres://user:pass@host:5432/app_production_queue
CACHE_DATABASE_URL=postgres://user:pass@host:5432/app_production_cache
CABLE_DATABASE_URL=postgres://user:pass@host:5432/app_production_cable
Créez ces bases supplémentaires dans votre instance Postgres, ou réduisez le bloc de production à une seule base principale si vous n'utilisez pas les adaptateurs Solid. Les deux choix se défendent. Ce qui casse tout, c'est de déployer avec trois des quatre variables non définies sans s'en rendre compte.
Étape 3 : le reste de l'environnement
RAILS_MASTER_KEY est le seul secret dont le conteneur a vraiment besoin. C'est le contenu de config/master.key, et Rails refusera de démarrer sans lui lorsque config.require_master_key est activé. Laissez-le comme variable d'exécution : la construction ne le lit pas.
RAILS_MAX_THREADS définit la taille du pool de connexions Active Record dans le database.yml généré, avec 5 par défaut. Si vous exécutez aussi plusieurs processus Puma au moyen de WEB_CONCURRENCY, votre nombre total de connexions est le produit des deux, et Postgres a un max_connections fini. Faites ce calcul avant d'augmenter l'un ou l'autre.
Étape 4 : les migrations
Vous avez deux options raisonnables, et une troisième qui semble juste sans l'être.
Laisser faire le point d'entrée. db:prepare crée la base si elle est absente et la migre si elle existe. Pour la plupart des applications, cela suffit, et c'est déjà branché.
Utiliser la commande de post-déploiement de Coolify. Dans les réglages du cycle de vie du déploiement, une commande de post-déploiement s'exécute dans le conteneur nouvellement construit, une fois le déploiement terminé. Y placer bundle exec rails db:migrate vous donne une étape de migration visible et réexécutable dans le journal de déploiement.
Le piège, c'est le champ de pré-déploiement juste à côté. Celui-là s'exécute dans le conteneur existant, avant le démarrage du nouveau : votre migration tournerait donc contre l'ancien code. Réservez-le au préchauffage de cache ou à un indicateur de maintenance, pas aux migrations livrées avec la version.
Étape 5 : les tâches en arrière-plan
Depuis Rails 8, Solid Queue est l'adaptateur Active Job par défaut. Il s'appuie sur la base de données et ne demande donc aucun Redis. Deux façons de l'exécuter :
- Lancez le superviseur avec
bin/jobscomme deuxième ressource Coolify pointant vers le même dépôt et la même image. Les tâches évoluent et redémarrent alors indépendamment de votre processus web. - Ou définissez
SOLID_QUEUE_IN_PUMA, ce qui exécute le superviseur à l'intérieur de Puma. Une application Rails 8 par défaut génère déjà la ligneplugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"]dansconfig/puma.rb: la variable est donc généralement la seule chose à ajouter. Le fichier README de Solid Queue documente les deux approches et recommande une base de file distincte, tout en prenant en charge une base unique partagée.
Sidekiq demeure le choix courant pour les files à haut débit, et il exige Redis : Sidekiq exige Redis 7.0+, Valkey 7.2+ ou Dragonfly 1.27+. Redis et Dragonfly sont des ressources en un clic dans Coolify, exécutées comme conteneurs sur la même VM. C'est donc un ajout modeste, pas un fournisseur de plus. Valkey ne figure pas parmi les ressources en un clic de Coolify : celui-là exige plutôt une ressource Docker Compose.
Étape 6 : domaine, TLS et vérification de l'état
Pointez un enregistrement A vers l'adresse IP de votre serveur, inscrivez l'URL complète dans le champ Domains de Coolify, puis redéployez. Coolify demande le certificat à Let's Encrypt et le renouvelle. La version détaillée se trouve dans domaines personnalisés.
Deux réglages Rails méritent un second regard à ce stade. Depuis Rails 8.1, un rails new par défaut génère config.assume_ssl et config.force_ssl en commentaire. Rails 8.0 les générait déjà actifs. Derrière le proxy de Coolify, vous voulez généralement les deux actifs : vérifiez config/environments/production.rb et décommentez-les si votre générateur les a laissés en commentaire.
Réglez ensuite le chemin de vérification de l'état de Coolify à /up, que Rails achemine vers rails/health#show par défaut. Si vous avez activé force_ssl, une vérification en HTTP recevra une redirection plutôt qu'un 200. La configuration de production générée fournit le correctif en commentaire, une ligne plus bas :
config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } }
Un dernier piège propre à Rails : les téléversements
La configuration générée définit config.active_storage.service = :local, qui écrit dans storage/ à l'intérieur du conteneur. Or, un système de fichiers de conteneur ne survit pas à un redéploiement. Attachez un volume de stockage persistant à ce chemin dans Coolify, ou faites pointer Active Storage vers un service compatible S3. Choisissez délibérément, parce que le mode de défaillance est la disparition silencieuse des fichiers téléversés au prochain déploiement, et non une erreur visible.
Ce que nous gérons, et ce que vous gérez
La précision s'impose, parce que « géré » ne veut pas dire la même chose d'une plateforme à l'autre.
Nous gérons : la VM à Toronto, le système d'exploitation et ses correctifs de sécurité, l'installation de Coolify et ses mises à jour, la surveillance de disponibilité de votre instance, et des instantanés hebdomadaires du serveur complet. Ces instantanés constituent une couche de reprise après sinistre et peuvent dater de sept jours : configurez donc les sauvegardes S3 de base de données de Coolify pour tout ce que vous ne pouvez pas vous permettre de perdre.
Vous gérez : votre code Rails, votre Dockerfile, vos variables d'environnement, vos migrations, votre superviseur de tâches, votre réglage de Postgres, ainsi que la répartition de la RAM et du processeur du serveur entre le processus web, le processus de tâches et la base de données.
Nous n'examinons pas votre Dockerfile, votre configuration Rails ni les versions de vos dépendances. Les étapes ci-dessus vous reviennent, et ce sont les mêmes que chez n'importe quel hébergeur Docker. Vous avez un accès root sur la VM : ces décisions restent donc les vôtres.
Les forfaits sont à prix fixe en dollars canadiens par mois, à partir de 45 $ pour 4 Go de RAM et 2 vCPU, sans facturation par service pour la base de données ou le processus de tâches. Ils partagent tout de même la RAM et le processeur du forfait, alors dimensionnez en conséquence. Les forfaits Starter et Pro comprennent un essai gratuit de 30 jours, assez pour déployer la vraie application, exécuter une vraie migration et voir ce que votre construction exige réellement avant de payer. Si vous lisez ceci pour des raisons de juridiction plutôt que de prix, notre page sur l'infrastructure canadienne couvre la propriété, la résidence des données et la question du CLOUD Act.
Mettez votre application Rails sur une infrastructure canadienne
Construction par Dockerfile, PostgreSQL en un clic et une VM dédiée à Toronto. 30 jours gratuits sur les forfaits Starter et Pro.