Rails 3

In questa pagina troverai le informazioni necessarie a comprendere i meccanismi interni di RubyOnRails 3.x e ad effettuare un deploy completo.

Quickstart

Se hai fretta, questi sono i passaggi per effettuare un deploy usando ruby 1.8.7 di sistema e urack.rb

Requisiti: ambiente ssh (consigliato su container da almeno 48 mega, o 6 processi da 48), dominio con almeno 1 processo da 96M o container da 96M. Migliore configurazione risorse: unico container da 128 mega utilizzato sia per ssh che per il deploy.

1) in locale (dalla directory della propria applicazione) lanciare

bundle pack

questo comando effettuera' una copia di cache delle gemme in vendor/cache (per evitare di doverle scaricare da remoto, operazione pesantissima, lentissima e che raramente funzionera' a causa delle risorse limitate)

2) caricare la directory dell'applicazione dentro la propria directory www su unbit

3) su unbit, via ssh, spostarsi nella directory dell'applicazione e lanciare bundle install usando la directory di cache

bundle187 install --path vendor/gemme --local

sui server unbit sono presenti molte versioni dei vari ambienti. bundle187 e' uno shortcut per richiamare bundler di ruby 1.8.7. --local forzera' l'uso della directory vendor/cache. --path e' dove vogliamo che siano istallate le gemme. Potete usare il path che volete.

se ottenete un errore sulla versione di sqlite, e' perche' quella di sistema e' un po' vecchiotta. In /opt/unbit ce ne sono di piu' recenti. editate il file .bundle/config nella vostra applicazione aggiungendo questa linea:

BUNDLE_BUILD__SQLITE3: --with-sqlite3-dir=/opt/unbit/sqlite373/

e rilanciate il bundle187 install come prima.

4) scaricate urack.rb da http://projects.unbit.it/uwsgi/browser/contrib/urack.rb

(attenzione, non fate copia e incolla, vi ritrovereste cn un file html, scaricate la versione originale dal link in fondo alla pagina trac)

5) copiate urack.rb nella directory public della vostra applicazione

6) sul pannello di controllo, nelle opzioni del dominio, impostate

docroot: nomeapp/public
upstream: abilitato
upstream_cmd: ruby187 urack.rb ../config.ru
upstream_checkfile: rails-style check

attenzione la docroot e' relativa a www, quindi se la vostra app e' in www/pippo la docroot sara' pippo/public

7) attendete 30 secondi e visitate il dominio

8) tutti gli errori vengono loggati nel file stderr_log nella propria home

Se volete approfondire i meccanismi interni, continuate a leggere...

Bundler (in locale)

la prima novita' introdotta e' Bundler, un sistema molto comodo per gestire le gemme e le loro dipendenze.

Nel momento in cui creeremo la nostra applicazione rails verra' anche generato un file Gemfile al cui interno sono elencate le gemme necessarie al nostro progetto.

source 'http://rubygems.org'

gem 'rails', '3.0.1'
gem 'sqlite3-ruby', :require => 'sqlite3'

La direttiva source indica da dove andranno scaricate le gemme non disponibili sul sistema, con gem invece si specificano le gemme e le loro versioni. L'attributo :require indica quale modulo ruby caricare in caso non ci sia corrispondenza con il nome della gemma.

Poniamo che la nostra applicazione fara' uso della gemma will_paginate, aggiungiamola quindi al Gemfile

{{{
source 'http://rubygems.org'

gem 'rails', '3.0.1'
gem 'sqlite3-ruby', :require => 'sqlite3'

gem 'will_paginate'

Ora siamo pronti a rendere disponibili le gemme alla nostra applicazione lanciando

bundle install

Ora in base alla configurazione del vostro sistema potreste trovarvi faccia a faccia con il primo problema. Se bundle install vi restituira' un errore di permessi significa che la vostra configurazione di rubygems non permette l'istallazione di gemme nello spazio utente ma solo system wide.

Nessun problema, bundler permette di istallare TUTTE le gemme di cui fa uso la vostra applicazione in una directory specifica.

Poniamo che la directory sara' vendor/gemme all'interno della nostra applicazione rails.

Semplicemente lanciamo

bundle install --path vendor/gemme

Bundler a questo punto prendera' le gemme di rails 3.0.1 e di sqlite3 dal vostro sistema e le copiera' in vendor/gemme, mentre scarichera' da http://rubygems.org will_paginate e la istallera' (ovviamente) in vendor/gemme

Se nel frattempo non e' esploso nulla potrete lanciare

./scripts/rails server

e vedrete la vostra applicazione girare

A questo punto potrete iniziare a sviluppare i vari controller/action ed eventualmente ad aggiungere ulteriori gemme al Gemfile.

Quando aggiungete delle gemme dovrete rilanciare

bundle install

il comando si occupera' di aggiornare il file Gemfile.lock (vedremo poi a cosa serve) e di scaricare/istallare le nuove gemme.

Il Gemfile.lock contiene la lista di dipendenze e versioni delle singole gemme necessarie all'applicazione. Se e' incongruente con il Gemfile, allora significa che qualcosa e' andato storto e bundler ve lo notifichera' appena proverete a lanciare un comando.

Se il bundle install non vuole saperne di funzionare, rimuovete il Gemfile.lock e il file .bundle/config (attenzione e' un file nascosto sui sistemi UNIX/POSIX) e ripartite da capo con

bundle install --path vendor/gemme

Comunque non dovrebbe mai capitarvi se siete ordinati nel seguire la procedura ;)

I piu' attenti avranno notato che la seconda volta il bundle install e' stato lanciato senza specificare il path, questo perche' dopo la prima volta viene salvato nel file .bundle/config. TENETELO A MENTE

Bundler in produzione

Siamo arrivati al momento fatidico, carichiamo online la nostra applicazione. A differenza del passato saremo tranquilli perche' tutte le gemme che ci servono sono gia' nella nostra applicazione.

Questa tranquillita' pero' svanira' presto se non avete usato in locale un sistema Linux 32bit (quelli usati in Unbit) o se qualcuna delle vostre gemme fa uso di librerie che non sono presenti sul server (caso raro ma possibile).

Ad esempio in locale usate MacOSX, quindi tutte le gemme native (ovvero quelle scritte in C che richiedono compilazione) saranno compilate per questa architettura, che (ovviamente) non funzionera' su di un sistema Linux.

Abbiamo 3 strade grazie a bundler. La prima (quella consigliata) e' di specificare nel Gemfile il percorso in cui bundler dovra' cercare la gemma. Questo perche' sui server Unbit tendiamo a fornire le gemme native proprio per evitare al cliente di dover ricompilare ogni cosa.

sqlite3-ruby e' ovviamente presente.

Da Novembre 2010 in /opt/unbit sono disponibili versioni di software aggiuntive che evitano la ricompilazione o l'utilizzo di packages.unbit.it. Una di queste e' ruby-1.8.7 (la versione minima necessaria per rails3). Dovremo quindi specificare nel Gemfile che vogliamo usare la sua versione di sqlite3-ruby.

gem 'sqlite3-ruby', '1.3.2', :path => '/opt/unbit/ruby187/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.3.2'

Fate attenzione alla versione (il secondo argomento della direttiva gem), se non la specificate il path verra' ignorato.

Ora se avete ssh vi sara' sufficiente lanciare

/opt/unbit/bin/bundle187 install --path vendor/gemme

Altrimenti potete aggiungere una chiamata "system" al motore di depoy che utilizzate.

Ad esempio in urack.rb potrete aggiungere:

system "/opt/unbit/bin/bundle187 install --path vendor/gemme"

Ricordatevi che UPSTREAM e' una shell (non interattiva ovviamente), quindi se volete potete anche specificare il comando bundle in upstream_cmd

A seconda delle vostre risorse Unbit, la procedura potrebbe richiedere un certo numero di secondi, ma vi accorgerete subito che la maggior parte del tempo viene inpiegata per scaricare i dati da http://rubygems.org. (e probabilmente questo massiccio download potrebbe non far funzionare nulla).

Vi starete chiedendo: "Ho gia' le gemme in locale perche' riscaricarle ?"

Giusta osservazione, e bundler ci viene nuovamente incontro

In locale lanciate

bundle pack

questo comando copiera' in vendor/cache tutti i file .gem necessari per il successivo utilizzo

Torniamo online e lanciamo

/opt/unbit/bin/bundle187 install --path vendor/gemme --local

La direttiva --local informa bundler che le gemme vanno tutte cercate in vendor/cache

Ora dovremmo esserci, e potrete passare all'avvio dell'applicazione

Il secondo metodo per gestire le gemme native (che sebbene sia il piu' rapido e' di sicuro quello piu' inelegante) e' usare la direttiva :platform

gem 'sqlite3-ruby', :platform => :mswin

Questa direttiva dira' a bundler di ignorare la gemma se non si e' su un sistema windows. Direi che il risultato e' facilmente immaginabile. Se una gemma viene ignorata, verra' usato il sistema standard per caricarla (e quindi verra' cercata nel sistema al momento del require)

L'ultimo metodo e' quello piu' "costoso", sia in termini di risorse che di tempo, ma permette di avere ambienti piu' "solidi" e congruenti con quelli locali.

Si lascia il Gemfile invariato e dopo aver rimosso il file .bundle/config (per simulare un ambiente vergine) si rilancia

/opt/unbit/bin/bundle187 install --path vendor/gemme --local

questo ricompilera' anche le gemme native.

La compilazione potrebbe lanciare diversi processi, quindi acertatevi di averne assegnati un bel numero o all'ssh o al dominio che lancera' bundler.

C'e' pero' un altro problema all'orizzonte, che probabilmente si presentera' compilando sqlite3-ruby.

Gli header di sqlite (cosi' come di molte altre librerie o applicativi) possono essere sparsi in diverse locazioni del filesystem. Ad esempio nel path standard di ricerca sara'possibile trovare gli header della versione sqlite distribuita con Ubuntu Hardy. E' una vecchia versione, che non puo' piu' ussere usata con le versioni recenti di sqlite3-ruby.

Gli header della versione piu' recente sono in /opt/unbit/sqlite373 (o qualcosa di simile, se saranno disponibili altre versioni). Dovremo quindi informare bundler che in fase di compilazione di sqlite3-ruby dovra' utilizzare questo percorso.

Per farlo si usa il file .bundle/config a cui aggiungeremo questa direttiva

BUNDLE_BUILD__SQLITE3-RUBY: --with-sqlite3-dir=/opt/unbit/sqlite373/

oppure per il piu' recente moduloe sqlite3:

BUNDLE_BUILD__SQLITE3: --with-sqlite3-dir=/opt/unbit/sqlite373/

La sintassi e' abbastanza intuitiva, si aggiunge a BUNDLE_BUILD il nome della gemma in maiuscolo e si specifica la direttiva da passare al compilatore.

Se qualche gemma in particolare vi da' problemi di compilazione e non sapete che direttiva usare contattate pure lo staff Unbit.

Quando le cose si rompono

Puo' capitare che nonostante seguendo questa guida, o studiando a memoria il tutorial sul sito ufficiale di bundler le procedure non funzionino. In questo caso eliminate il file .bundle/config e il Gemfile.lock per ricominciare da capo. Non pretendete che tutto vi funzioni al primo colpo, bundler e' molto potente ma e' anche molto giovane.

Un po' di arte

Se usate un sistema di controllo di versione, come git o mercurial vi starete chiedendo come gestire il Gemfile e le sue differenze tra locale e produzione.

Per prima cosa escludete la directory .bundle dal versionamento, in ogni caso verra' ricreata in automatico (e correttamente ogni volta che lanciate il bundle install).

Approfittate poi della potenza di ruby nei DSL. Gemfile non e' altro che un file ruby a cui sono state aggiunte delle nuove direttive. Tutti i processi Unbit ereditano la variabile d'ambiente UNBIT (che contiene l'id numerico dell'utente) quindi potete usare qualche magia del genere

if ENV['UNBIT']
  gem 'sqlite3-ruby', '1.3.2', :path => '/opt/unbit/ruby187/lib/ruby/gems/1.8/gems/sqlite3-ruby-1.3.2'
else
  gem 'sqlite3-ruby'
end

E ora andiamo online...

Ci sono diversi applicativi disponibili per effettuare il deploy di una applicazione Rails3.

Attualmente sono supportati

urack.rb (consigliato, supporta i thread di ruby 1.9)

uwsgi_rack (sperimentale ma altamente performante supporta le fiber di ruby 1.9)

unicorn

rackup

Per avviarli potete fare riferimento alla pagina Upstream

Ricordatevi sempre che Rails 3 richiede ruby 1.8.7 (almeno) quindi l'interprete ruby da usare e' ruby187 anziche' ruby (che corrisponde a ruby 1.8.6)

Rails3 (l'ultima modifica รจ del 2011-09-22 05:23:47, fatta da RobertoDeIoris)