How to Deploy a Smalltalk service to Google Cloud

Deploying a program to run as a service in the cloud can be done for any programming language, including Smalltalk. The trick involves creating a Docker container that contains the program and which can then be deployed as different kinds of services.

The problem here is that Docker can be tricky to wrap you head around the first time(s), it surely was for me, anyway. But if you're able to do it, then the world is your oyster, because all the major cloud providers (and most minor too) are based on deploying docker containers. Even if it is sometimes hidden from view, that is what  happens underneath the sheets.

But luckily, you don't actually need to understand how Docker containers works inside out to be able to use it, as long as you're able to create one. What I am describing here are hopefully a number of small steps you can follow to deploy your own, first cloud service based on Smalltalk. I will be using Pharo as an example, but the instructions should work for any Smalltalk, really.

The steps to take to deploy a Smalltalk program to the cloud is the following;

  1. Create a simple Web service in Smalltalk, which listens to port 8080 (it is a default port for several cloud providers, but any port will do as long as you configure things correctly)
  2. Create a Docker container that when run, starts Pharo with the current image and/or loads code from a source-code tonel file.
  3. Deploy the Docker container to a cloud provider to be started as a service.

When speaking about a 'service', there are two different kinds of services that all major cloud vendors offer; cloud functions (called Lambdas on AWS) or virtual machines. The difference between them is that cloud functions are only run when there is an incoming request for them, and are then spun down, whereas virtual machines run 24/7 and can do long-running background tasks.

Economy plays a role in which you chose, since cloud functions are essentially free to use on any major cloud provider, if you can manage to keep the traffic to them below 200K requests/month. That is the free tier limit on Google Cloud but other vendors have similar generous free tiers. If you want to run a vm (virtual machine), however you will be paying for each CPU second it is up, which can amount to $10-$20/month at minimum capacity. Both AWS and Google Cloud do allow you to run one small, low-powered vm for free, which can be rebooted without warning, but still something.

I will be using cloud function as a deployment target, because it is simple and easy to manage. Also, I will be cheating a little bit since I'm using Google Cloud, I can send the instructions to build the docker image for my service to Google's build system. Then I'll point out to google which build image I want to deploy as what kind of service.

Torsten Bergmann (@astares) has written an excellent post on how to create docker containers which run Pharo services, which I recommend that you read first, to get a better understanding of Docker in a Smalltalk context.

The basics is that you need to create a plain text-file named 'Dockerfile', in which you write instructions to docker on which operating system the container is based on, which libraries and programs should be installed, which files should be copied over into the image containing source code to be compiled, configuration files to be used or maybe even certificates to authenticate with external services, if needed.

Docker will then be instructed to read this file and will produce a docker image as a result. This image will be stored as file(s) somewhere on the disk of the machine where docker is run, but you will never ever access them directly. Docker images are always started, accessed and administered using the 'docker' command.

Begin by creating the two files from Torsten's docker tutorial (updated to use a more recent version of Pharo and to use debian as a base, which works better in GCP for some reason);

Dockerfile

######################################
# Based on Debian image
###################################### 
FROM debian

######################################
# Basic project infos 
###################################### 
LABEL maintainer="Your Name" 

###################################### 
# Update debian apt and install some tools
######################################
RUN  apt-get update \
  && apt-get install -y wget \
  && apt-get install -y git \
  && apt-get install -y unzip \
  && rm -rf /var/lib/apt/lists/*

###################################### 
# Have an own directory for the tool 
######################################
RUN mkdir webapp
WORKDIR webapp

######################################
# Download Pharo using Zeroconf & start script
######################################
RUN wget -O- https://get.pharo.org/64/80+vm | bash

COPY load.st load.st

RUN ./pharo Pharo.image load.st

######################################
# Expose port 8080 of Zinc outside the container
######################################
EXPOSE 8080

######################################
# Finally run headless as server
######################################
CMD ./pharo --headless Pharo.image --no-quit

load.st 

ZnServer startDefaultOn: 8080.

SmalltalkImage current snapshot: true andQuit: true



The Dockerfile prepares the image, installs required base services and then copies and runs the file 'load.st' which starts an instance of the Zinc web-server and saves the state of the image so that when the docker container is started, the web server is already running in the Pharo image.

In practice, you would have a metacello commands in your load.st file which installs the program you are working on (using Zinc or one of the other web frameworks indirectly), and all its dependencies, from github or something like it, and then starts that instead. But for now, this small example is enough to get started.

OK, now we have the blueprint for a cloud service, great! We can now build a local docker container, following the instructions in Torsten's article (which could be a good idea, to see and understand the process), or we can install the Google Cloud SDK and tell it to use these files to create a new cloud function, just like that. 

And here comes the next tricky part (which is the same for any cloud provider I've come across so far), you need to register as a potential customer, so you are able to create your own cloud services. Even if you're only using the free tier, which will cost you nothing at all, you will still need to register a credit card. I got a bad feeling about this the first time I did it, but it's just the way it is, sadly. 

Go to https://console.cloud.google.com/ to register yourself, to be able to deploy to the cloud.

As part of the registration process you will be asked to name your first project. Projects in google cloud are ways to organize your deployments and other services. Often one has one project for 'testing' and one for 'production', as an example. 

When you are registered and have a project defined, its time to install the SDK for GCP (Google Cloud Platform), see instructions here; https://cloud.google.com/sdk/docs/install

After this is done, you should be able to run the 'gcloud' command, which let you list, control and deploy a large number of different services in your project.

OK, so far, so good. To build and then deploy your code as a cloud function, you write the following;

gcloud builds submit --tag gcr.io/PROJECT-ID/helloworld

Where PROJECT-ID is the actual name of your project, like 'foobar-1a770' or something similar.

When the build is finished (it can take 1.5 minutes or more), it is time to tell google to deploy the built docker image (which is now residing inside google cloud) as a cloud function;

   gcloud run deploy --image gcr.io/PROJECT-ID/helloworld --platform managed
You will then be asked in which region of the world you would like to deploy the cloud function , and after deployment you will see which url you can use to access the cloud functions, something like;

https://helloworld-eszmdol7vq-lz.a.run.app/

Which will then return the default Zinc web-server homepage



Now, if you go to the google cloud web console, you can also verify that the cloud function is deployed, as well as see some statistics;

https://console.cloud.google.com/run?project=PROJECT-ID




There you go, please leave comments or questions, if you spot any bugs or if there is something you want me to expand on. I'm also mostly on the Pharo discord server; https://pharo.org/community



Comments