Bereitstellen einer Rails-App mit Git Hooks unter Ubuntu 14.04

Einführung

In diesem Tutorial zeigen wir Ihnen, wie Sie Git-Hooks verwenden, um die Bereitstellung der Produktionsumgebung Ihrer Rails-Anwendung auf einem entfernten Ubuntu 14.04-Server zu automatisieren. Mithilfe von Git-Hooks können Sie Ihre Anwendung bereitstellen, indem Sie Ihre Änderungen einfach auf einen Produktionsserver übertragen, anstatt manuell Datenbankmigrationen durchführen zu müssen. Wenn Sie weiterhin an Ihrer Anwendung arbeiten, können Sie durch das Einrichten automatisierter Bereitstellungen wie Git-Hooks auf lange Sicht Zeit sparen.

Dieses spezielle Setup verwendet einen einfachen Git-Hook nach dem Empfang, zusätzlich zu Puma als Anwendungsserver, Nginx als Reverse-Proxy für Puma und PostgreSQL als Datenbank.

Wenn Sie Git Hooks noch nicht kennen und mehr erfahren möchten, bevor Sie fortfahren, lesen Sie dieses Tutorial: https://www.digitalocean.com/community/tutorials/how-to-use-git-hooks-to-automate-development -und-Bereitstellungsaufgaben [Verwendung von Git-Hooks zur Automatisierung von Entwicklungs- und Bereitstellungsaufgaben].

Voraussetzungen

Sie benötigen Zugriff auf einen Nicht-Root-Benutzer, der Superuser-Rechte auf Ihrem Ubuntu-Server besitzt. In unserem Beispiel-Setup verwenden wir einen Benutzer namens "++". Dieses Tutorial zeigt Ihnen, wie Sie dies einrichten: Initial Server Setup with Ubuntu 14.04. Wenn Sie die Bereitstellung ohne Eingabe eines Kennworts durchführen möchten, müssen Sie SSH-Schlüssel einrichten.

Sie müssen Ruby auf Ihrem Server installieren. Wenn Sie dies noch nicht getan haben, können Sie es zusammen mit Rails unter https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-with-rbenv-on-ubuntu installieren -14-04 [rbenv] oder https://www.digitalocean.com/community/tutorials/installationsanleitung-ruby-on-rails-on-ubuntu-14-04- using-rvm[RVM].

Sie benötigen außerdem eine Rails-Anwendung, die in einem Git-Repository auf Ihrem lokalen Entwicklungscomputer verwaltet wird. Wenn Sie noch keine haben und mitmachen möchten, stellen wir Ihnen eine einfache Beispiel-App zur Verfügung.

Lass uns anfangen!

Installieren Sie PostgreSQL

In den meisten Production Rails-Umgebungen wird PostgreSQL als Datenbank verwendet. Installieren Sie diese jetzt auf Ihrem Server.

Aktualisieren Sie auf Ihrem * Produktions * -Server apt-get:

sudo apt-get update

Dann installiere PostgreSQL mit diesen Befehlen:

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

Benutzer der Produktionsdatenbank erstellen

Benennen Sie den Benutzer der Produktionsdatenbank mit dem Namen Ihrer Anwendung, um die Sache zu vereinfachen. Wenn Ihre Anwendung beispielsweise "Anwendungsname" heißt, sollten Sie einen PostgreSQL-Benutzer wie folgt erstellen:

sudo -u postgres createuser -s

Wir möchten das Kennwort des Datenbankbenutzers festlegen. Geben Sie die PostgreSQL-Konsole folgendermaßen ein:

sudo -u postgres psql

Legen Sie dann das Kennwort für den Datenbankbenutzer "appname" wie folgt fest:

\password

Geben Sie Ihr gewünschtes Passwort ein und bestätigen Sie es.

Beenden Sie die PostgreSQL-Konsole mit folgendem Befehl:

\q

Jetzt können wir Ihre Anwendung mit den richtigen Datenbankverbindungsinformationen konfigurieren.

Bereiten Sie Ihre Rails-Anwendung vor

Auf Ihrem * Entwicklungscomputer *, höchstwahrscheinlich Ihrem lokalen Computer, bereiten wir Ihre Anwendung für die Bereitstellung vor.

Optional: Erstellen Sie eine Rails-Anwendung

Idealerweise haben Sie bereits eine Rails-Anwendung, die Sie bereitstellen möchten. In diesem Fall können Sie diesen Unterabschnitt überspringen und die entsprechenden Ersetzungen vornehmen, während Sie den Anweisungen folgen. Wenn nicht, müssen Sie zunächst eine neue Rails-Anwendung erstellen.

Diese Befehle erstellen eine neue Rails-Anwendung mit dem Namen "appname" in unserem Ausgangsverzeichnis. Fühlen Sie sich frei, den hervorgehobenen "App-Namen" durch etwas anderes zu ersetzen:

cd ~
rails new

Dann wechseln Sie in das Anwendungsverzeichnis:

cd

Für unsere Beispiel-App generieren wir einen Scaffold Controller, damit unsere Anwendung etwas anzeigt:

rails generate scaffold Task title:string note:text

Stellen wir nun sicher, dass sich unsere Anwendung in einem Git-Repository befindet.

Initialisiere Git Repo

Wenn sich Ihre Anwendung aus irgendeinem Grund noch nicht in einem Git-Repository befindet, initialisieren Sie sie und führen Sie ein erstes Commit durch.

Wechseln Sie auf Ihrem * Entwicklungscomputer * in das Verzeichnis Ihrer Anwendung. In unserem Beispiel heißt unsere App "appname" und befindet sich in unserem Home-Verzeichnis:

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

Jetzt optimieren wir unsere Anwendung, um sie für die Verbindung mit unserer PostgreSQL-Produktionsdatenbank vorzubereiten.

Datenbankkonfiguration aktualisieren

Wechseln Sie auf Ihrem * Entwicklungscomputer * in das Verzeichnis Ihrer Anwendung, falls Sie noch nicht dort sind. In unserem Beispiel heißt unsere App "appname" und befindet sich in unserem Home-Verzeichnis:

cd

Öffnen Sie nun die Datenbankkonfigurationsdatei in Ihrem bevorzugten Editor. Wir verwenden "+ vi +":

vi config/database.yml

Suchen Sie den Abschnitt * production * in der Datenbankkonfiguration Ihrer Anwendung und ersetzen Sie ihn durch die Verbindungsinformationen Ihrer Produktionsdatenbank. Wenn Sie das Beispiel genau befolgt haben, sieht es ungefähr so ​​aus (ersetzen Sie gegebenenfalls Werte):

config / database.yml Auszug

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

Speichern und schließen. Dies gibt an, dass die Produktionsumgebung der Anwendung eine PostgreSQL-Datenbank mit dem Namen "appname_production" auf dem lokalen Host, dem Produktionsserver, verwenden soll. Beachten Sie, dass der Benutzername und das Kennwort der Datenbank auf Umgebungsvariablen festgelegt sind. Diese werden später auf dem Server angegeben.

Update Gemfile

Wenn Ihr Gemfile das PostgreSQL-Adapter-Gem + pg + und das angegebene Puma-Gem noch nicht enthält, sollten Sie diese jetzt hinzufügen.

Öffnen Sie die Gemfile Ihrer Anwendung in Ihrem bevorzugten Editor. Wir werden hier "+ vi +" verwenden:

vi Gemfile

Fügen Sie dem Gemfile die folgenden Zeilen hinzu:

Gemfile-Auszug

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

Speichern und schließen. Dies gibt an, dass die Produktionsumgebung die Edelsteine ​​"+ pg " und " puma +" verwenden soll.

Konfigurieren Sie Puma

Bevor Sie Puma konfigurieren, sollten Sie die Anzahl der CPU-Kerne Ihres Servers ermitteln. Mit dem folgenden Befehl können Sie auf Ihrem Server problemlos darauf zugreifen:

grep -c processor /proc/cpuinfo

Fügen Sie nun auf Ihrer * Entwicklungsmaschine * die Puma-Konfiguration zu + config / puma.rb + hinzu. Öffnen Sie die Datei in einem Texteditor:

vi config/puma.rb

Kopieren Sie diese Konfiguration und fügen Sie sie in die Datei ein:

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

Ändern Sie die Anzahl "+ Arbeiter +" in die Anzahl der CPU-Kerne Ihres Servers. In diesem Beispiel wird davon ausgegangen, dass Sie 2 Kerne haben.

Speichern und schließen. Dadurch wird Puma mit dem Speicherort Ihrer Anwendung und dem Speicherort der Sockets, Protokolle und PIDs konfiguriert. Sie können die Datei jederzeit ändern oder andere erforderliche Optionen hinzufügen.

Übernehmen Sie Ihre letzten Änderungen:

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

Generieren Sie vor dem Fortfahren einen geheimen Schlüssel, der für die Produktionsumgebung Ihrer App verwendet wird:

rake secret
rake secret sample output:29cc5419f6b0ee6b03b717392c28f5869eff0d136d8ae388c68424c6e5dbe52c1afea8fbec305b057f4b071db1646473c1f9a62f803ab8386456ad3b29b14b89

Sie werden die Ausgabe kopieren und verwenden, um Ihre Anwendung "+ SECRET_KEY_BASE" im nächsten Schritt festzulegen.

Erstellen Sie ein Puma-Upstart-Skript

Erstellen wir ein Upstart-Init-Skript, damit wir Puma problemlos starten und stoppen und sicherstellen können, dass es beim Booten gestartet wird.

Laden Sie auf Ihrem * Produktionsserver * das Jungle Upstart-Tool aus dem Puma GitHub-Repository in Ihr Home-Verzeichnis herunter:

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

Öffnen Sie nun die bereitgestellte Datei "+ puma.conf +", damit wir den Puma-Bereitstellungsbenutzer konfigurieren können:

vi puma.conf

Suchen Sie nach den beiden Zeilen, in denen "+ setuid " und " setgid +" angegeben sind, und ersetzen Sie "apps" durch den Namen Ihres Bereitstellungsbenutzers und Ihrer Bereitstellungsgruppe. Wenn Ihr Bereitstellungsbenutzer beispielsweise "deploy" heißt, sollten die Zeilen folgendermaßen aussehen:

puma.conf Auszug 1 von 2

setuid
setgid

Suchen Sie nun die folgende Zeile: + exec / bin / bash << 'EOT' +. Fügen Sie die folgenden Zeilen hinzu, und stellen Sie dabei sicher, dass Sie den PostgreSQL-Benutzernamen und das Kennwort sowie das zuvor erstellte Rake-Geheimnis ersetzen:

puma.conf Auszug 2 von 2

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

Speichern und schließen.

Kopieren Sie nun die Skripte in das Upstart-Services-Verzeichnis:

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

Das Skript + puma-manager.conf + verweist auf + / etc / puma.conf + für die Anwendungen, die es verwalten soll. Lassen Sie uns diese Inventardatei jetzt erstellen und bearbeiten:

sudo vi /etc/puma.conf

Jede Zeile in dieser Datei sollte der Pfad zu einer Anwendung sein, die von + puma-manager + verwaltet werden soll. Wir werden unsere Anwendung in einem Verzeichnis mit dem Namen "appname" im Ausgangsverzeichnis unseres Benutzers bereitstellen. In unserem Beispiel ist dies der folgende Pfad (aktualisieren Sie unbedingt den Pfad, in dem sich Ihre App befindet):

/etc/puma.conf

/home//

Speichern und schließen.

Jetzt ist Ihre Anwendung so konfiguriert, dass sie beim Start über Upstart gestartet wird. Dies bedeutet, dass Ihre Anwendung auch nach dem Neustart Ihres Servers gestartet wird. Denken Sie daran, dass wir die Anwendung noch nicht bereitgestellt haben und sie daher noch nicht starten möchten.

Installieren und konfigurieren Sie Nginx

Um die Anwendung für das Internet zugänglich zu machen, sollten wir Nginx als Webserver verwenden.

Installieren Sie Nginx mit apt-get:

sudo apt-get install nginx

Öffnen Sie nun den Standard-Serverblock mit einem Texteditor:

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

Ersetzen Sie den Inhalt der Datei durch den folgenden Codeblock. Stellen Sie sicher, dass Sie die hervorgehobenen Teile durch den entsprechenden Benutzernamen und Anwendungsnamen ersetzen (zwei Speicherorte):

/ 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;
}

Speichern und schließen. Dadurch wird Nginx als Reverse-Proxy konfiguriert, sodass HTTP-Anforderungen über einen Unix-Socket an den Puma-Anwendungsserver weitergeleitet werden. Sie können nach Belieben Änderungen vornehmen.

Wir werden Nginx vorerst nicht neu starten, da die Anwendung noch nicht auf dem Server vorhanden ist. Als nächstes bereiten wir die Bewerbung vor.

Bereiten Sie Production Git Remote vor

Installieren Sie auf Ihrem * Produktionsserver * git mit apt-get:

sudo apt-get install git

Erstellen Sie dann ein Verzeichnis für das Remote-Repository. Wir erstellen ein Bare-Git-Repository im Home-Verzeichnis mit dem Namen "appname_production". Sie können Ihr Remote-Repository beliebig benennen (außer, dass Sie es nicht in "+ ~ / appname +" einfügen, da wir die Anwendung dort bereitstellen):

mkdir ~/
cd ~/
git init --bare

Da dies ein nacktes Repository ist, gibt es kein Arbeitsverzeichnis und alle Dateien, die sich in einem herkömmlichen Setup in .git befinden, befinden sich im Hauptverzeichnis selbst.

Wir müssen einen Post-Receive-Git-Hook erstellen. Dies ist das Skript, das ausgeführt wird, wenn der Produktionsserver einen Git-Push empfängt. Öffnen Sie die Datei + hooks / post-receive + in Ihrem Editor:

vi hooks/post-receive

Kopieren Sie das folgende Skript und fügen Sie es in die Datei + post-receive + ein:

Hooks / Post erhalten

#!/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

Achten Sie darauf, die folgenden hervorgehobenen Werte zu aktualisieren:

  • + GIT_DIR +: Das Verzeichnis des zuvor erstellten Bare-Git-Repositorys

  • + WORK_TREE +: das Verzeichnis, in dem Sie Ihre Anwendung bereitstellen möchten (dies sollte mit dem Speicherort übereinstimmen, den Sie in der Puma-Konfiguration angegeben haben)

  • + APPNAME_DATABASE_USER +: PostgreSQL-Benutzername (erforderlich für Rechenaufgaben)

  • + APPNAME_DATABASE_PASSWORD +: PostgreSQL-Passwort (erforderlich für Rake-Aufgaben)

Als nächstes sollten Sie die Befehle zwischen den Kommentaren + # Start Deploy Tasks + und + # End Deploy Tasks + überprüfen. Dies sind die Befehle, die jedes Mal ausgeführt werden, wenn der Hauptzweig an die Produktions-Git-Fernbedienung gesendet wird (+ appname_production +). Wenn Sie sie unverändert lassen, versucht der Server, Folgendes für die Produktionsumgebung Ihrer Anwendung zu tun:

  • Führen Sie den Bundler aus

  • Erstellen Sie die Datenbank

  • Migrieren Sie die Datenbank

  • Assets vorkompilieren

  • Starten Sie Puma neu

  • Starten Sie Nginx neu

Wenn Sie Änderungen vornehmen oder eine Fehlerprüfung hinzufügen möchten, können Sie dies hier tun.

Wenn Sie das Post-Receive-Skript überprüft haben, speichern Sie es und beenden Sie es.

Als nächstes machen Sie das Skript ausführbar:

chmod +x hooks/post-receive

Passwortloses Sudo

Da der Post-Receive-Hook sudo-Befehle ausführen muss, können Sie dem Deployment-Benutzer die Verwendung von + sudo + ohne Kennwort gestatten (ersetzen Sie Ihren Deployment-Benutzernamen hier, wenn er anders ist):

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

Auf diese Weise kann der Benutzer "+ deploy " die Befehle " sudo +" ausführen, ohne ein Kennwort anzugeben. Beachten Sie, dass Sie möglicherweise einschränken möchten, welche Befehle der Bereitstellungsbenutzer mit Superuser-Berechtigungen ausführen kann. Sie sollten mindestens die SSH-Schlüsselauthentifizierung verwenden und die Kennwortauthentifizierung deaktivieren.

Fügen Sie Production Git Remote hinzu

Nachdem wir alles auf dem Produktionsserver eingerichtet haben, fügen wir den Produktions-Git Remote zum Repository unserer Anwendung hinzu.

Stellen Sie auf Ihrem * Entwicklungscomputer * sicher, dass Sie sich im Verzeichnis Ihrer Anwendung befinden:

cd

Fügen Sie dann eine neue Git-Fernbedienung mit dem Namen "production" hinzu, die auf das Bare-Git-Repository "+ appname_production +" verweist, das Sie auf Ihrem Produktionsserver erstellt haben. Ersetzen Sie den Benutzernamen (deploy), die Server-IP-Adresse und den Namen des Remote-Repositorys (appname_production):

git remote add production @:

Jetzt kann Ihre Anwendung mit einem Git-Push bereitgestellt werden.

In der Produktion bereitstellen

Nach all den Vorbereitungen können Sie Ihre Anwendung jetzt auf Ihrem Produktionsserver bereitstellen, indem Sie den folgenden git-Befehl ausführen:

git push production master

Dadurch wird Ihre lokale Hauptniederlassung einfach auf die zuvor erstellte Produktionsfernbedienung verschoben. Wenn die Produktionsfernbedienung den Push empfängt, führt sie das Hook-Skript + post-receive + aus, das wir zuvor eingerichtet haben. Wenn Sie alles richtig eingerichtet haben, sollte Ihre Anwendung jetzt unter der öffentlichen IP-Adresse Ihres Produktionsservers verfügbar sein.

Wenn Sie unsere Beispielanwendung verwendet haben, sollten Sie in der Lage sein, in einem Webbrowser auf "+ http: /// tasks +" zuzugreifen und Folgendes zu sehen:

Fazit

Jedes Mal, wenn Sie eine Änderung an Ihrer Anwendung vornehmen, können Sie denselben git push-Befehl ausführen, um ihn auf Ihrem Produktionsserver bereitzustellen. Dies allein sollte Ihnen über die gesamte Laufzeit Ihres Projekts viel Zeit sparen.

In diesem Lernprogramm wurde nur der Hook nach dem Empfang behandelt. Es gibt jedoch mehrere andere Hook-Typen, die zur Verbesserung der Automatisierung Ihres Bereitstellungsprozesses beitragen können. Lesen Sie dieses Tutorial, um mehr über Git-Hooks zu erfahren: How To Use Git Hooks zur Automatisierung von Entwicklungs- und Bereitstellungsaufgaben!