Deploying Pharo Application
Written on July 4 2012.
This blog post was written a long time ago and may not reflect my current opinion or might be technically out of date. Read with a grain of salt.
People sometimes asks me how to deploy Smalltalk applications. I’ve only worked with Squeak and Pharo with server side application so I only covers those two dialects in that context.
It all start easy. Basically, you write a script that you can use with a process monitoring daemon (I use monit but any will do the trick). This daemon will start/restart/stop your application with your script. So far, I never had any problems with this system.
Now how does your startup script should look like? Here is an overview of the different possibilities. Please comment if you use an other strategy.
Create an image locally and upload it
That’s the most basic scenario. You create your image locally, load everything you need and then upload it to your server with S/FTP. Slow and painful, you want to avoid this process.
Load everything all the time
Your script takes a fresh image, load your Metacello configuration and hopla, it’s ready to go. You never save the image. It is used as a runtime and there’s no need to save it. I love this approach for its simplicity. It is also pretty clean as you never rot your image and everything is wiped out when you restart.
Acutally it looks like a regular web application in, say, Ruby. Ruby loads your code and the dependent gems and run your code.
Unfortunately it has a huge drawback. Metacello will look at all your dependencies and load the versions you defined. You need to rely on other people configurations and hope that their repo are still reachable. Have you ever encoutered a broken Metacello configuration? How many time squeaksource has been down lately? The recent outage with Lukas Renggli repository (which contained many open source projects) also shows the limitation of this model.
Another issue is the time it takes to load packages with Monticello. Most of my projects depends on Seaside, Magritte, Cloudfork and others. Loading all those can take up to 20 minutes. It means that you need to wait every time your application restarts. Annoying.
There’s a GSOC project going on that will solve this problem by providing binary packages (so you don’t need to recompile everything you load). It’s not there yet and you need a binary version of all the project you depend on.
Prepare a base image with CI server
For this one, you load your project and its dependencies once in an image. You save it. Then you tell your process monitoring daemon to just launch it. Once it started, you never save it. If it crashes, you simply restart the prepared image.
With this approach, you need to generate the base image. You can do it manually but a continuous integration server can help a lot. You can create a hook that regenerate the base image when you update your Metacello configuration for example.
This scenario removes the problem of loading time. When your application crashes, it can restart instantly, you don’t need to reload everything. But you need a CI server to automate the construction of the image.
The first approach is clearly not optimal. It works for very small project but does not scale at all. Ideally, your deployment process should be as smooth as possible. A Heroku like deployment would be super cool to have but so far Smalltalkers all have their own scripts, there are no standardized solutions.
Note that those strategies show their limitation only at the first launch or when they restart. In many situations, you can update your code when it’s running, without restarting the image.
Smalltalker, what is your deployment process?