heroku – Deployment so einfach wie ein push


Für ein Projekt an dem ich gerade privat arbeite, bin ich auf heroku gestoßen. heroku ist ein sogenannter Plattform as a Service (PaaS) – Provider. Das ganze ist damit Teil des Cloud-Computing-Hypes – zusammen mit Infrastructure as a Service (IaaS) und Software as a Service (SaaS).

Auch wenn ich insgesamt nicht viel von dem ganzen Cloud-Computing-Hype halte, kommt es doch ab und an vor, dass ich Software schreiben möchte, in die ich wenig Arbeit stecken möchte, und die dynamische GUI braucht, etc. Kurzum, wenn es mal eben schnell gehen soll, dann bin ich mittlerweile auf dem Stand, dass ich mir mal eben was in Ruby on Rails Scaffolde (ja, ich weiß, böse), einfach weil es sehr schnell gemacht ist, und ich mich um so wenig wie Möglich kümmern muss. Der Nachteil ist natürlich, dass das ganze “wenig” Portabel ist.

Das “wenig” steht bewusst in Anführungszeichen, da mein erstes Programm, dass sich ein wenig weiter verbreitet hatte, ein in Visual Basic geschriebenes Programm war, und daher nur auf Windows lief. Ich hätte damals gerne schon Java verwendet, aber mit AWT kannte ich mich noch nicht aus (und Swing war damals noch verrucht, weil es neu war), und langes GUI-Gebastele wollte ich nicht – das lies das Projekt dass ich realisierte auch nicht zu.

Allerdings – die Weitergabe als Executable gestaltete sich recht einfach. Würde ich selbiges mit einer in Rails geschriebenen Applikation machen, so müsste die Person erst einmal Ruby und Rails bei sich installieren (in der Richtigen Version), dann in der Konsole ein “bundle install” durchführen, eventuell dabei vorher noch das Gemfile an die lokalen Gegebenheiten anpassen, den Server starten, und dann im Webbrowser die Applikation aufrufen zu können. Suboptimal, wenn man nur schnelles Feedback zur App möchte, die man gerade geschrieben hat. Klar, man könnte auch auf seinem Rechner den Server laufen lassen, müsste dann aber ständig IPs mitteilen, oder sich per DynDNS eine Weiterleitung einrichten, den Rechner dann immer laufen haben (oder immer dann, wenn die andere Seite denn dann mal gucken möchte) und wenn man dann wie ich auf nem Laptop entwickelt und grad auch keinen stationären Rechner da hat, ist das ganze wieder suboptimal.

Hier kommt dann – für mich – heroku ins Spiel. Aber heroku ist natürlich auch für alle interessant, die SaaS-Projekte realisieren wollen, ohne sich um die Infrastruktur und Plattform kümmern zu wollen 😉

Die Bedienung von heroku ist kinderleicht. Einzige Voraussetzung ist, dass man sein Projekt in ein git-Repository verwaltet (leider nur git, keine Mercurial-Unterstützung).

Ist das Projekt einmal als git-Repository initialisiert, installiert man sich das Gem heroku über

pygospa@lalaith ~/demo_app % git init
pygospa@lalaith ~/demo_app (git)-[master] % bundle install heroku

(Bemerkung: Eingabezeilen sind nach dem Systemprompt % angegeben, und die Zeilen grau hervorgehoben; nicht hervorgehobene Zeilen sind Ausgaben des Systems nach der Eingabe)

Während dessen kann man schon mal auf die Seite navigieren und sich einen Account bei heroku anlegen – den brauchen wir nämlich. Interessant ist vorher vielleicht auch die Information darüber, wie heroku funktioniert und wie es eventuell mit den Kosten aussieht, wenn man professionelle Features benötigt (für die Standard-Sachen ist ziemlich viel ziemlich kostenlos!)

Ist heroku installiert, melden wir uns einmal mit

pygospa@lalaith ~/demo_app (git)-[master] % heroku login
Enter your heroku credentials.
Email: pygospa@gmail.com
Password (typing will be hidden):
Authentication successful.

an. Beim ersten Start guckt heroku dann auch gleich, ob es unter ~/.ssh einen öffentlichen SSH-Key finden kann. Falls nicht, fragt es, ob es einen generieren soll und lädt den dann gleich hoch. Schon hier zeigt sich, wie einfach und praktisch heroku sich bedienen lässt.

Jetzt kommt eine kleinen Feinheit. Da heroku PostgreSQL als Datenbank benutzt, Rails standardmäßig mit SQLite arbeitet, und alles andere bedeutet, dass man eine weitere Datenbank installieren muss (was man bei großen Produktivsystemen auch sicherlich sollte – für meine Zwecke ist das aber irgendwie wieder mit Kanonen auf Spatzen geschossen), editieren wir das Gemfile wie folgt:

gem 'sqlite3', :group => [:development, :test]
group :production do
     gem 'thin'
     gem 'pg'
end

Damit weisen wir Rails an, für die Environments “development” (Standard-Environment, das über ‘rails server’ genutzt wird) und “test” weiterhin mit sqlite zu arbeiten. heroku läuft standardmäßig als “production”-Environment, und hier wollen wir dann das gem ‘thin’ und ‘pg’ statt dem ‘sqlite3’ installieren und nutzen.

Jetzt muss natürlich das Gemfile.lock neu erstellt werden, also einmal erneut

pygospa@lalaith ~/demo_app (git)-[master] % bundle install

aufgerufen werden. Wenn man aber, wie ich, PostgreSQL garnicht installiert hat, knallt es natürlich noch einmal, da Rails versucht, alle drei Umgebungen zu installieren. Daher dann statt dessen wie folgt:

pygospa@lalaith ~/demo_app (git)-[master] % bundle install --without production

und alles ist gut.

Mehr ist es nicht, was an “Vorarbeit” geleistet werden muss. Wer wie ich programmiert, hat immer ein fertiges Gemfile als Muster im home-Verzeichnis liegen, das er sich für solche zwecke einmal anlegt, und dann in jedes Projekt kopieren kann.

Jetzt verknüpfen wir das Projekt mit einem neuen Projekt auf heroku, indem wir

pygospa@lalaith ~/demo_app (git)-[master] % heroku create
Creating limitless-temple-5146... done, stack is cedar
http://limitless-temple-5146.herokuapp.com/ | git@heroku.com:limitless-temple-5146.git

aufrufen.

Aus der Ausgabe wird ersichtlich, dass heroku hier nun ein Projekt anlegt, zu dem eine Subdomain angelegt wird, und ein remote git-Branch initialisiert wird.

Wer mit den zufällig generierten Projektnamen nicht so glücklich ist (in diesem fall “limitless-temple-5146”) kann das ganze, soweit die Domain auch verfügbar ist, editieren:

pygospa@lalaith ~/demo_app (git)-[master] % heroku rename "myAppName"
Renaming limitless-temple-5146 to my-app-name... failed
! Name is already taken
pygospa@lalaith ~/demo_app (git)-[master] % heroku rename my-fancy-app-name
Renaming limitless-temple-5146 to my-fancy-app-name... done
http://my-fancy-app-name.herokuapp.com/ | git@heroku.com:my-fancy-app-name.git
git remote heroku updated

Fertig. Jetzt kommen wir zum spaßigen Teil. Nachdem wir also nun unser Projekt fleißig bearbeitet haben, und einen Stand im lokalen master-Branch des git-Repositories haben, geht das Deployment wie folgt:

pygospa@lalaith ~/demo_app (git)-[master] % git push heroku master
Counting objects: 63, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (49/49), done.
Writing objects: 100% (63/63), 26.06 KiB, done.
Total 63 (delta 2), reused 0 (delta 0)

-----> Ruby/Rails app detected
-----> Installing dependencies using Bundler version 1.3.2
       Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin --deployment
       Fetching gem metadata from https://rubygems.org/.........
       Fetching gem metadata from https://rubygems.org/..
       Installing rake (10.0.4)
(...)
       Installing uglifier (1.3.0)
       Your bundle is complete! It was installed into ./vendor/bundle
       Cleaning up the bundler cache.
-----> Writing config/database.yml to read from DATABASE_URL
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       Asset precompilation completed (12.52s)
-----> Rails plugin injection
       Injecting rails_log_stdout
       Injecting rails3_serve_static_assets
-----> Discovering process types
       Procfile declares types      -> (none)
       Default types for Ruby/Rails -> console, rake, web, worker

-----> Compiled slug size: 10.8MB
-----> Launching... done, v6
       http://my-fancy-app-name.herokuapp.com deployed to heroku

To git@heroku.com:my-fancy-app-name.git
 * [new branch]      master -> master

Fertig. Ehrlich! Der Branch heroku wurde in der ./git/config als neuer Remote-Branch angelegt, der auf das Repository git@heroku.com:my-fancy-app-name.git verweist.

[remote "heroku"]
         url = git@heroku.com:my-fancy-app-name.git
         fetch = +refs/heads/*:refs/remotes/heroku/*

Das Pushen des master Branches auf dieses Repository veranlasst das Senden aller Dateien (später aller Änderungen) an das Repository, und kaum das das passiert, wird bei heroku veranlasst, dass

bundle install –without development:test –path vendor/bundle –binstubs vendor/bundle/bin –deployment

aufgerufen wird, und ein Server mit unserer App gestartet wird. Wer immernoch zweifelt, kann danach ganz einfach mal

pygospa@lalaith ~/demo_app (git)-[master] % heroku ps
=== web: `bundle exec thin start -R config.ru -e $RAILS_ENV -p $PORT`
web.1: up 2013/04/04 14:15:03 (~ 3m ago)

eingeben, und sollte mit einer Webserverinstanz (die Anzahl lässt sich auch manuell beeinflussen) begrüßt werden.

Oder man geht einfach mal auf die URL http://my-fancy-app-name.herokuapp.com/ im Browser aufrufen.

Zum Debuggen ganz hilfreich: Auch auf die Server-Konsole besteht Zugriff:

pygospa@lalaith ~/demo_app (git)-[master] % heroku run rails console
Running `rails console` attached to terminal... up, run.2503
Connecting to database specified by DATABASE_URL
Loading production environment (Rails 3.2.8)
irb(main):001:>

Und man kann natürlich allerlei mit Rakefiles hantieren, sich die Logs anschauen, den verwendeten Webserver (Default WEBrick), etc. ändern.

Übrigens ist heroku – welches lange Zeit nur für Rails existiert hat, mittlerweile nicht mehr ausschließlich auf Rails beschränkt. Unterstützt werden jetzt auch Java inklusive Spring-, Hibernate-, Play!– und Grails-Framework. Weiterhin genutzt werden muss natürlich git, und das Build-Tool Maven, sowie Jetty als Container. Dafür gibt es aber ein angenehmes Eclipse-Plugin.

Und neben Java wird dann auch noch der Lisp-Dialekt Clojure, Python, Scala und Node.js unterstützt.

Advertisements

One thought on “heroku – Deployment so einfach wie ein push

Please comment. I really enjoy your thoughts!

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s