Smalltalk in The Cloud

Geoffroy Couprie is a consultant in software security and a independant developer. After testing Clever Cloud for a while, he challenged himself trying to run Smalltalk on our PaaS. Here's the recap of his findings.

The Smalltalk world offers a radically different way to create and run software, and I have always loved to tinker with it. Thanks to the recent work around Docker at Clever Cloud, it is now possible to run Pharo Smalltalk apps, even Seaside ones, on this PaaS.

Thinking in Smalltalk

One of the most interesting features of Smalltalk is the image, which is a file containing a list of serialized objects. When you start your virtual machine, you load the image. When you stop, you serialise everything: classes, methods, instances of classes, windows, even running web servers. And when you start, you get back your environment in the same state. Even writing code is different: you are not editing a file, you are editing the implementation of a method, serialised like everything else in the image. That way, you can modify code while it is running easily.



The traditional method for deploying a web server consists in preparing the image with the code, and uploading the whole image on the server. This is at odds with deployment process at Clever Cloud, based on a simple Git push. So it requires a few steps.

Docker

Thanks to the recent developments around Docker support, it is now possible to run any language or platform on these servers. So I prepared two images, one to install Pharo Smalltalk on an archlinux Docker container, and the other, based on the first, to install the Seaside web framework.

There is nothing tricky in the first image, except needing to install lib32-zlib, lib32-ncurses and lib32-bzip2 to run the 32 bits VM on a 64 bits CPU.

The second image runs a .st file to download Seaside, remove default Seaside apps and deactivate the debug bar:

Gofer new
url:'http://www.smalltalkhub.com/mc/Seaside/MetacelloConfigurations/main';
package: 'ConfigurationOfSeaside3';
load.
((Smalltalk at: #ConfigurationOfSeaside3) project version: #stable) load.

WAAdmin applicationDefaults removeParent: WADevelopmentConfiguration instance.
WADispatcher default handlers keys do:[:name | WAAdmin unregister:name].
Smalltalk snapshot: true andQuit: true.

Now, we have an image ready for deployment, and usable for all the future Seaside projects.

Preparing the code for deployment

We could save the image in a git repository, and push the whole file to Clever Cloud, but that would be too easy. What if we could send just the required code through git? Here comes FileTree, a library pre-installed in Pharo, that you can use to export code from the image and add it to a Git repository.

First, let's get some code to deploy. I will spare you the details, just get the WebCounter example from the Seaside book, it is doable under 10 minutes.

Done? Alright. Choose a folder that will contain the code you will push to the server, and git init in that folder. Now open the Monticello browser, add a new repository, select "filetree://" then choose your git folder.



Now select your WebCounter package in the Monticello browser, and save the code.



It should now appear in file form in the git folder:

$ tree .
.
└── WebCounter.package
    ├── WebCounter.class
    │   ├── README.md
    │   ├── instance
    │   │   ├── decrease.st
    │   │   ├── increase.st
    │   │   ├── initialize.st
    │   │   └── renderContentOn..st
    │   ├── methodProperties.json
    │   └── properties.json
    ├── monticello.meta
    │   ├── categories.st
    │   ├── initializers.st
    │   ├── package
    │   └── version
    └── properties.json

Loading the code

Now that we have an export of the Seaside component, we will create a Docker image to load the code. First, we need a small script to give the virtual machine at startup, to load the code and run it:

"this uses FileTree to load back the code from the /home/deploy folder"
(MCFileTreeRepository new directory: '/home/deploy' asFileReference) packageDescriptionsFromReadableFileNames  do:
  [:name || version |
  version := (MCFileTreeRepository new directory: '/home/deploy' asFileReference) versionFromFileNamed: name first, '.package'.
  [version load ]
        on: MCMergeOrLoadWarning
        do: [ :ex | [ ex load  ] on: MCNoChangesException do: [] ] ].

FileStream stdout nextPutAll: 'WebCounter installed'; lf.

"the Clever Cloud platform expects the app to listen on the 8080 port"
ZnZincServerAdaptor startOn: 8080.

"Register the code we just loaded on the /webcounter address"
WAAdmin register: WebCounter asApplicationAt: 'webcounter'.

Save that code as seaside.st, then we will create the Dockerfile to make it work on the server:

# -*- sh -*-
FROM geal/archlinux-seaside
MAINTAINER Geoffroy Couprie, contact@geoffroycouprie.com

ADD . /home/deploy

EXPOSE 8080

CMD ./pharo Pharo.image ./deploy/seaside.st

It reuses the archlinux-seaside image I prepared previously, copies the code from the repository in /home/deploy, then starts the image with the code loading script.

With this, you can build and run the image to test it:

$ docker build -t "geal/seaside-example" .
$ docker run -t -i -p 8080:8080 geal/seaside-example /bin/bash
[root@8e726df1bf4e home]# ./pharo Pharo.image ./deploy/seaside.st

UndefinedObject>>DoIt (WebCounter is Undeclared)
WebCounter installed

If you are on Linux, the website will be available on http://localhost:8080/webcounter. If you use OS X, run boot2docker ip, then access the server at http://<virtual machine IP>:8080/webcounter.

Creating the app on Clever Cloud and deploying

Go to https://console.clever-cloud.com, create a new application of type Docker, then get the git URL for your app, and do in your repository:

$ git remote add clever git+ssh://git@push.par.clever-cloud.com/<your app id>.git
$ git push clever master

And that's it! You can now access the Seaside component at http://<your_app_id>.cleverapps.io/webcounter.

At each new version of the code, export it to Git then push again, and the platform will redeploy everything automatically, rebuilding the Docker containers and the Pharo images. Now, you just need to add a few components to store state, like a database or S3 component, and you are good to go!

All the code is available on Github if you need to play with it:



Blog

À lire également

Clever Cloud at VivaTech 2025: demonstration of Clever AI, new partnerships and support for startups

At VivaTech 2025, Clever Cloud is highlighting a number of strategic announcements and innovations in line with its vision of a sovereign, open and resilient cloud. The team will be present in various pavilions, unveiling Clever AI for the first time, presenting a partnership with Grist, an open source data platform, signing a partnership for development in North Africa and stepping up its support for the startup ecosystem.
Company

Grist Labs and Clever Cloud Announce Strategic Partnership to Deliver Sovereign, Scalable Data Solutions in Europe

Grist Labs, creators of the modern, open-source data tool, and Clever Cloud, a leading European Platform-as-a-Service (PaaS) cloud service provider, today announced a strategic partnership to deliver secure, sovereign hosting and streamlined distribution of Grist services across Europe.
Company Press

What is native cloud?

The world of software development is changing at breakneck speed. In an economic environment where digital technology plays an increasingly central role, companies are looking to create applications that are ever more responsive, scalable and resilient.
Company