Une critique que l'on voit assez souvent vis à vis de Ruby on Rails est qu'il est difficile de déployer une application. C'est effectivement difficile de trouver un hébergeur "clef en main" pour gérer votre application Rails mais si vous avez la main sur le serveur, déployer une application Rails n'est pas forcément plus compliqué qu'une autre technologie. Aussi, je vous propose de voir comment déployer une application Ruby on Rails sur un serveur à l'aide de Capistrano et Puma.
Côté serveur
Avant de vouloir déployer il va falloir préparer le serveur qui va accueillir notre application.
Installation de Ruby
La première étape commence donc par l'installation de Ruby. Cette installation peut se faire de plusieurs manières :
sudo apt-get install ruby
, en s'assurant que la version présente dans les dépôts corresponde à la version nécessaire à votre application- rvm, permet de faire cohabiter plusieurs version de ruby et ainsi de sélectionner la version à installer
- rbenv, permet la même chose que RVM avec quelques différences
Une fois Ruby installé, vous devez aussi installer bundler qui va permettre d'installer les différentes dépendances de votre application.
gem install bundler
Installation de MySQL
Notre application persiste les données via MySQL il est donc nécessaire d'installer ce SGBD et de créer une base de données pour notre projet :
# On install mysql
sudo apt-get install mysql-server mysql-client libmysqlclient-dev
# On se connecte à mysql
mysql -uroot -p
mysql> CREATE DATABASE ma_base_de_donnees;
mysql> exit;
Installation de NodeJS
NodeJS est utilisé par le gestionnaire d'assets de Rails pour précompiler les JS / CSS.
sudo apt-get install nodejs
Préparation des dossiers
Enfin la dernière étape est la création des dossiers et fichiers qui seront utilisé lors de notre déploiement. Cette étape va variée suivant les projets mais voici la configuration de base.
mkdir -p /home/user/monsite/shared/log
mkdir -p /home/user/monsite/shared/tmp/cache
mkdir -p /home/user/monsite/shared/tmp/pids
mkdir -p /home/user/monsite/shared/tmp/sockets
mkdir -p /home/user/monsite/config
# On remplit les informations concernant la base de données / clefs secrètes
vim /home/user/monsite/config/secrets.yml
vim /home/user/monsite/config/database.yml
Le serveur est maintenant prêt à accueillir notre déploiement.
Côté local
Maintenant que notre serveur est prêt, nous allons configurer notre environnement local pour déployer notre projet Ruby on Rails à l'aide de capistrano.
On versionne
Pour utiliser capistrano il est essentiel que votre projet soit versionné et publié sur un dépôt distant. Vous pouvez utiliser n'importe quel service ou le publier sur votre propre serveur via SSH.
Capistrano
Nous allons ajouter capistrano aux dépendances de notre projet ainsi que quelques gems pour ajouter des étapes de déploiement supplémentaires
group :development do
# ...
gem 'capistrano', '~> 3.6'
gem 'capistrano-rails', '~> 1.1'
gem 'capistrano-rvm', '~> 0.1.2'
gem 'capistrano3-puma', github: "seuros/capistrano-puma"
# ...
end
On installe en suite ces nouvelle dépendances et on initialise capistrano :
bundle install
cap install
Cette dernière commande aura pour effet de générer plusieurs fichiers que l'on va pouvoir modifier pour indiquer à capistrano comment doit se dérouler le déploiement. On commence par modifier le fichier Capfile
afin de charger les recettes capistrano correspondantes à notre application.
# /Capfile
# Load DSL and set up stages
require "capistrano/setup"
# Include default deployment tasks
require "capistrano/deploy"
# Include custom deployment tasks
require 'capistrano/rvm'
require 'capistrano/rails'
require 'capistrano/puma'
require 'capistrano/puma/nginx'
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
On va ensuite modifier le fichier config/deploy.rb
pour personnaliser notre déploiement.
lock '3.6.1'
set :application, 'MonApplication'
set :repo_url, 'git@mon-serveur-git.com'
set :deploy_to, '/home/user/monsite'
# Les fichiers / dossiers partagés entre les releases
append :linked_files, 'config/database.yml', 'config/secrets.yml'
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets'
# La configuration nginx / puma
set :nginx_config_name, 'mon_application'
set :nginx_server_name, 'monapplication.fr'
set :puma_workers, 2
Et le serveur sur lequel on va déployer via config/deploy/production.rb
server 'monapplication.fr', user: 'monuser', roles: %w{app web db}, ssh_options: { forward_agent: true }
Enfin, si vous le souhaitez, capistrano-puma vous permet de personnaliser les template utilisés pour définir la configuration de puma et de nginx. Vous pouvez générer ces templates à l'aide de la commande rails g capistrano:nginx_puma:config
(les fichiers de template se situeront alors dans le dossier config/deploy/templates
)
Upload de la configuration
Maintenant que notre projet est configuré on peut passer à l'envoi des configurations de puma et d'nginx. Heureusement pour nous, capistrano-puma nous simplifie grandement la tâche et 2 commandes suffisent :
cap production puma:config
cap production puma:nginx_config
Il faudra alors faire un sudo service nginx reload
côté serveur pour qu'il prenne en compte cette nouvelle configuration.
Le déploiement
Maintenant que tout est prêt nous pouvons enfin passer au déploiement via la commande
cap production deploy
Cette commande va se charger de :
- Cloner le dépôt dans un nouveau dossier (releases/{timestamp})
- Faire les liens symboliques vers le dossier shared
- Installer les dépendances via un
bundle install
- Précompiler les assets
- Lancer les migrations nécessaires
- Démarrer ou redémarrer puma en utilisant le fichier de configuration
Et voila ! Votre site est déployé et fonctionnel ! Maintenant, dès que vous faites des modifications à votre projet il vous suffit de publier vos modifications via git et d'utiliser ensuite la commande cap production deploy
à nouveau pour que vos changements se retrouvent en ligne.