Comment déployer une application Rails avec Git Hooks sur Ubuntu 14.04

introduction

Dans ce didacticiel, nous allons vous montrer comment utiliser les points d’ancrage Git pour automatiser le déploiement de l’environnement de production de votre application Rails sur un serveur distant Ubuntu 14.04. L’utilisation de hooks Git vous permettra de déployer votre application en transmettant simplement vos modifications à un serveur de production, au lieu de devoir extraire et exécuter manuellement des opérations telles que l’exécution de migrations de bases de données. Tandis que vous continuez à travailler sur votre application, la configuration d’une forme de déploiement automatisé, telle que les crochets Git, vous permettra de gagner du temps à long terme.

Cette configuration particulière utilise un simple crochet Git "post-réception", en plus de Puma en tant que serveur d’applications, de Nginx en tant que proxy inverse pour Puma et de PostgreSQL en tant que base de données.

Si vous êtes nouveau sur Git Hooks et souhaitez en savoir plus avant de continuer, lisez ce tutoriel: https://www.digitalocean.com/community/tutorials/how-to-use-git-hooks-to-automate-development -and-deployment-tasks [Comment utiliser les crochets Git pour automatiser les tâches de développement et de déploiement].

Conditions préalables

Vous aurez besoin d’un accès à un utilisateur non root disposant des privilèges de superutilisateur sur votre serveur Ubuntu. Dans notre exemple de configuration, nous allons utiliser un utilisateur appelé ++. Ce tutoriel va vous montrer comment configurer cela: Initial Initial Server Setup with Ubuntu 14.04. Si vous souhaitez déployer sans entrer de mot de passe, veillez à configurer les clés SSH.

Vous devrez installer Ruby sur votre serveur. Si vous ne l’avez pas déjà fait, vous pouvez l’installer avec Rails à l’aide de https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-with-rbenv-on-ubuntu. -14-04 [rbenv] ou RVM.

Vous aurez également besoin d’une application Rails gérée dans un référentiel git sur votre ordinateur de développement local. Si vous n’en avez pas et que vous souhaitez suivre, nous vous fournirons un exemple d’application simple.

Commençons!

Installer PostgreSQL

La plupart des environnements de production Rails utilisent PostgreSQL comme base de données. Installez-la donc maintenant sur votre serveur.

Sur votre serveur * production *, mettez à jour apt-get:

sudo apt-get update

Ensuite, installez PostgreSQL avec ces commandes:

sudo apt-get install postgresql postgresql-contrib libpq-dev

Créer un utilisateur de base de données de production

Pour simplifier les choses, appelons l’utilisateur de la base de données de production le même nom que le nom de votre application. Par exemple, si votre application s’appelle “appname”, vous devez créer un utilisateur PostgreSQL comme ceci:

sudo -u postgres createuser -s

Nous voulons définir le mot de passe de l’utilisateur de la base de données. Entrez donc la console PostgreSQL de la manière suivante:

sudo -u postgres psql

Ensuite, définissez le mot de passe de l’utilisateur de la base de données, "appname" dans l’exemple, comme suit:

\password

Entrez votre mot de passe souhaité et confirmez-le.

Quittez la console PostgreSQL avec cette commande:

\q

Nous sommes maintenant prêts à configurer votre application avec les informations de connexion de base de données appropriées.

Préparez votre application Rails

Sur votre * machine de développement *, probablement votre ordinateur local, nous préparerons votre application en vue de son déploiement.

Facultatif: Créer une application Rails

Idéalement, vous avez déjà une application Rails que vous souhaitez déployer. Si tel est le cas, vous pouvez ignorer ce paragraphe et procéder aux substitutions appropriées en suivant. Sinon, la première étape consiste à créer une nouvelle application Rails.

Ces commandes créeront une nouvelle application Rails, nommée «appname», dans notre répertoire personnel. N’hésitez pas à remplacer le «nom de l’application» en surbrillance par quelque chose d’autre:

cd ~
rails new

Puis changez dans le répertoire de l’application:

cd

Pour notre exemple d’application, nous allons générer un contrôleur d’échafaudage afin que notre application ait quelque chose à afficher:

rails generate scaffold Task title:string note:text

Maintenant, assurons-nous que notre application est dans un référentiel git.

Initialiser Git Repo

Si votre application ne se trouve pas déjà dans un référentiel Git pour une raison quelconque, initialisez-la et effectuez une validation initiale.

Sur votre * machine de développement *, accédez au répertoire de votre application. Dans notre exemple, notre application s’appelle "appname" et se trouve dans notre répertoire personnel:

cd
git init
git add -A
git commit -m 'initial commit'

Nous allons maintenant ajuster notre application pour la préparer à la connexion à notre base de données de production PostgreSQL.

Mise à jour de la configuration de la base de données

Sur votre * machine de développement *, accédez au répertoire de votre application si vous n’y êtes pas déjà. Dans notre exemple, notre application s’appelle "appname" et se trouve dans notre répertoire personnel:

cd

Ouvrez maintenant le fichier de configuration de la base de données dans votre éditeur favori. Nous allons utiliser + vi +:

vi config/database.yml

Recherchez la section * production * de la configuration de la base de données de votre application et remplacez-la par les informations de connexion de votre base de données de production. Si vous avez suivi exactement l’exemple mis en place, cela ressemblera à quelque chose comme ça (remplacez les valeurs le cas échéant):

extrait de config / database.yml

production:
 <<: *default
 host: localhost
 adapter: postgresql
 encoding: utf8
 database:
 pool: 5
 username: <%= ENV['_DATABASE_USER'] %>
 password: <%= ENV['_DATABASE_PASSWORD'] %>

Sauvegarder et quitter. Cela spécifie que l’environnement de production de l’application doit utiliser une base de données PostgreSQL appelée «appname_production» sur le serveur de production localhost. Notez que le nom d’utilisateur et le mot de passe de la base de données sont définis sur des variables d’environnement. Nous les préciserons plus tard sur le serveur.

Mettre à jour Gemfile

Si votre Gemfile ne dispose pas déjà de la gem adaptateur PostgreSQL ', + pg + `, et de la gem Puma spécifiée, vous devez les ajouter maintenant.

Ouvrez le fichier Gemfile de votre application dans votre éditeur favori. Nous allons utiliser + vi + ici:

vi Gemfile

Ajoutez les lignes suivantes au fichier Gemfile:

Extrait de Gemfile

group :production do
 gem 'pg'
 gem 'puma'
end

Sauvegarder et quitter. Cela spécifie que l’environnement + production doit utiliser les gemmes` + pg + et + puma + `.

Configurer Puma

Avant de configurer Puma, vous devez rechercher le nombre de cœurs de processeur de votre serveur. Vous pouvez facilement y arriver, sur votre serveur, avec cette commande:

grep -c processor /proc/cpuinfo

Maintenant, sur votre * machine de développement *, ajoutez la configuration de Puma à + ​​config / puma.rb +. Ouvrez le fichier dans un éditeur de texte:

vi config/puma.rb

Copiez et collez cette configuration dans le fichier:

config / puma.rb

# Change to match your CPU core count
workers

# Min and Max threads per worker
threads 1, 6

app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"

# Default to production
rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env

# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"

# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true

# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app

on_worker_boot do
 require "active_record"
 ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
 ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end

Changez le nombre de + travailleurs + par le nombre de cœurs de processeur de votre serveur. L’exemple suppose que vous avez 2 cœurs.

Sauvegarder et quitter. Cela configure Puma avec l’emplacement de votre application et l’emplacement de ses sockets, journaux et PID. N’hésitez pas à modifier le fichier ou à ajouter toute autre option dont vous avez besoin.

Commettez vos modifications récentes:

git add -A
git commit -m 'added pg and puma'

Avant de poursuivre, générez une clé secrète qui sera utilisée pour l’environnement de production de votre application:

rake secret
rake secret sample output:29cc5419f6b0ee6b03b717392c28f5869eff0d136d8ae388c68424c6e5dbe52c1afea8fbec305b057f4b071db1646473c1f9a62f803ab8386456ad3b29b14b89

Vous allez copier le résultat et l’utiliser pour définir votre application + SECRET_KEY_BASE à l’étape suivante.

Créer un script Puma Upstart

Créons un script d’initialisation Upstart pour pouvoir démarrer et arrêter Puma facilement et pour nous assurer qu’il démarrera au démarrage.

Sur votre * serveur de production *, téléchargez l’outil Jungle Upstart du référentiel Puma GitHub dans votre répertoire personnel:

cd ~
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma-manager.conf
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma.conf

Ouvrez maintenant le fichier + puma.conf + fourni, afin de pouvoir configurer l’utilisateur de déploiement Puma:

vi puma.conf

Recherchez les deux lignes spécifiant + setuid + et + setgid +, et remplacez «applications» par le nom de votre utilisateur et de votre groupe de déploiement. Par exemple, si votre utilisateur de déploiement s’appelle «deploy», les lignes doivent ressembler à ceci:

extrait de puma.conf 1 sur 2

setuid
setgid

Recherchez maintenant la ligne avec ceci: + exec / bin / bash << 'EOT' +. Ajoutez les lignes suivantes en dessous, en vous assurant de substituer le nom d’utilisateur et le mot de passe PostgreSQL, ainsi que le secret de rake que vous avez créé précédemment:

extrait de puma.conf 2 sur 2

 export _DATABASE_USER=''
 export _DATABASE_PASSWORD=''
 export SECRET_KEY_BASE=''

Sauvegarder et quitter.

Maintenant, copiez les scripts dans le répertoire des services Upstart:

sudo cp puma.conf puma-manager.conf /etc/init

Le script + puma-manager.conf + fait référence à + ​​/ etc / puma.conf + pour les applications qu’il devrait gérer. Créons et modifions maintenant ce fichier d’inventaire:

sudo vi /etc/puma.conf

Chaque ligne de ce fichier doit être le chemin d’une application que vous voulez gérer avec + puma-manager +. Nous allons déployer notre application dans un répertoire nommé "appname" dans le répertoire de base de nos utilisateurs. Dans notre exemple, ce serait le suivant (assurez-vous de mettre à jour le chemin d’accès à l’emplacement de votre application:

/etc/puma.conf

/home//

Sauvegarder et quitter.

Votre application est maintenant configurée pour démarrer au démarrage, via Upstart. Cela signifie que votre application démarrera même après le redémarrage de votre serveur. N’oubliez pas que l’application n’a pas été déployée et que nous ne souhaitons pas la démarrer pour l’instant.

Installer et configurer Nginx

Pour rendre l’application accessible à Internet, nous devrions utiliser Nginx en tant que serveur Web.

Installez Nginx en utilisant apt-get:

sudo apt-get install nginx

Ouvrez maintenant le bloc serveur par défaut avec un éditeur de texte:

sudo vi /etc/nginx/sites-available/default

Remplacez le contenu du fichier par le bloc de code suivant. Assurez-vous de remplacer les pièces surlignées par le nom d’utilisateur et le nom d’application appropriés (deux emplacements):

/ etc / nginx / sites-available / default

upstream app {
   # Path to Puma SOCK file, as defined previously
   server unix:/home///shared/sockets/puma.sock fail_timeout=0;
}

server {
   listen 80;
   server_name localhost;

   root /home///public;

   try_files $uri/index.html $uri @app;

   location @app {
       proxy_pass http://app;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
       proxy_redirect off;
   }

   error_page 500 502 503 504 /500.html;
   client_max_body_size 4G;
   keepalive_timeout 10;
}

Sauvegarder et quitter. Cela configure Nginx en tant que proxy inverse. Ainsi, les demandes HTTP sont transférées au serveur d’applications Puma via un socket Unix. N’hésitez pas à apporter des modifications à votre convenance.

Nous nous retiendrons de redémarrer Nginx pour le moment, car l’application n’existe pas encore sur le serveur. Nous préparerons ensuite l’application.

Préparer la production Git Remote

Sur votre * serveur de production *, installez git avec apt-get:

sudo apt-get install git

Créez ensuite un répertoire pour le référentiel distant. Nous allons créer un référentiel Git nu dans le répertoire de base appelé «appname_production». N’hésitez pas à nommer votre référentiel distant comme vous le souhaitez (sauf à ne pas le mettre dans + ~ / / appname + car c’est là que nous déploierons l’application):

mkdir ~/
cd ~/
git init --bare

Puisqu’il s’agit d’un référentiel nu, il n’y a pas de répertoire de travail et tous les fichiers situés dans .git dans une configuration conventionnelle se trouvent dans le répertoire principal même.

Nous devons créer git hook après réception, qui est le script qui s’exécutera lorsque le serveur de production recevra un push Git. Ouvrez le fichier + hooks / post-receive + dans votre éditeur:

vi hooks/post-receive

Copiez et collez le script suivant dans le fichier + post-receive +:

crochets / post-réception

#!/bin/bash

GIT_DIR=/home/
WORK_TREE=/home/
export _DATABASE_USER=''
export _DATABASE_PASSWORD=''

export RAILS_ENV=production
. ~/.bash_profile

while read oldrev newrev ref
do
   if [[ $ref =~ .*/master$ ]];
   then
       echo "Master ref received.  Deploying master branch to production..."
       mkdir -p $WORK_TREE
       git --work-tree=$WORK_TREE --git-dir=$GIT_DIR checkout -f
       mkdir -p $WORK_TREE/shared/pids $WORK_TREE/shared/sockets $WORK_TREE/shared/log

       # start deploy tasks
       cd $WORK_TREE
       bundle install
       rake db:create
       rake db:migrate
       rake assets:precompile
       sudo restart puma-manager
       sudo service nginx restart
       # end deploy tasks
       echo "Git hooks deploy complete"
   else
       echo "Ref $ref successfully received.  Doing nothing: only the master branch may be deployed on this server."
   fi
done

Assurez-vous de mettre à jour les valeurs en surbrillance suivantes:

  • + GIT_DIR +: le répertoire du référentiel Git nu que vous avez créé précédemment

  • + WORK_TREE +: le répertoire dans lequel vous souhaitez déployer votre application (il doit correspondre à l’emplacement que vous avez spécifié dans la configuration de Puma)

  • + APPNAME_DATABASE_USER +: Nom d’utilisateur PostgreSQL (requis pour les tâches rake)

  • + APPNAME_DATABASE_PASSWORD +: Mot de passe PostgreSQL (requis pour les tâches rake)

Ensuite, vous devriez passer en revue les commandes entre les tâches + # start deploy + + et + # end deploy taches + . Ce sont les commandes qui seront exécutées chaque fois que la branche master est poussée sur le git de production à distance (+ appname_production +`). Si vous les laissez tels quels, le serveur tentera de procéder comme suit pour l’environnement de production de votre application:

  • Run bundler

  • Créer la base de données

  • Migrer la base de données

  • Précompiler les actifs

  • Redémarrer Puma

  • Redémarrez Nginx

Si vous souhaitez apporter des modifications ou ajouter une vérification d’erreur, n’hésitez pas à le faire ici.

Une fois que vous avez terminé de réviser le script de post-réception, enregistrez et quittez.

Ensuite, rendez le script exécutable:

chmod +x hooks/post-receive

Sudo sans mot de passe

Comme le hook post-réception doit exécuter des commandes sudo, nous allons permettre à l’utilisateur déployé d’utiliser un mot de passe sans mot de passe + sudo + (remplacez votre nom d’utilisateur deploy ici s’il est différent):

sudo sh -c 'echo " ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/90-deploy'

Cela permettra à l’utilisateur + deploy + d’exécuter des commandes + sudo + sans fournir de mot de passe. Notez que vous voudrez probablement limiter les commandes que l’utilisateur de déploiement peut exécuter avec les privilèges de superutilisateur. Au minimum, vous voudrez utiliser l’authentification par clé SSH et désactiver l’authentification par mot de passe.

Ajouter Production Git Remote

Maintenant que tout est configuré sur le serveur de production, ajoutons le git de production distant au référentiel de notre application.

Sur votre * machine de développement *, assurez-vous d’être dans le répertoire de votre application:

cd

Ajoutez ensuite un nouveau git distant nommé «production» qui pointe vers le référentiel Git nu `` + appname_production + `, que vous avez créé sur votre serveur de production. Remplacez le nom d’utilisateur (deploy), l’adresse IP du serveur et le nom du référentiel distant (appname_production):

git remote add production @:

Votre application est maintenant prête à être déployée avec un git push.

Déployer en production

Avec toute la préparation que vous avez effectuée, vous pouvez maintenant déployer votre application sur votre serveur de production en exécutant la commande git suivante:

git push production master

Cela pousse simplement votre branche maître locale vers la télécommande de production que vous avez créée précédemment. Lorsque la télécommande de production reçoit le push, elle exécute le script de hook + post-receive + que nous avons précédemment configuré. Si vous configurez tout correctement, votre application devrait maintenant être disponible à l’adresse IP publique de votre serveur de production.

Si vous avez utilisé notre exemple d’application, vous devriez pouvoir accéder à + ​​http: /// tasks + dans un navigateur Web et voir quelque chose comme ceci:

image: https: //assets.digitalocean.com/articles/rails_githooks/tasks.png [Exemple d’application Rails]

Conclusion

Chaque fois que vous apportez une modification à votre application, vous pouvez exécuter la même commande git push à déployer sur votre serveur de production. Cela seul devrait vous faire gagner beaucoup de temps au cours de la vie de votre projet.

Ce tutoriel ne concerne que le hook «post-réception», mais il existe plusieurs autres types de hooks qui peuvent aider à améliorer l’automatisation de votre processus de déploiement. Lisez ce tutoriel pour en savoir plus sur les hooks Git: Comment utiliser Git Crochets pour automatiser les tâches de développement et de déploiement!