Building Pharo VM on Alpine Linux in Docker

3 December 2019

I've put up a Dockerfile that builds the Pharo pharo.cog.spur.minheadless VM on Alpine Linux within Docker. This allows one to build said VM without having to first create an Alpine Linux installation such as through VirtualBox.

This is a multi-stage Dockerfile. The Pharo VM is built in an Alpine Linux 'build' container. Then the VM files are copied into a fresh Alpine Linux Docker image. The resulting Pharo VM Docker image is ~14 MB.

The output Docker image contains the Pharo VM only and is not runnable by itself. It is intended to be used as a base to build your own Docker image containing your application-specific Pharo image.

Tested on Ubuntu 18.04 and MacOS Mojave.

Edit: Changes to OpenSmalltalk VM source tree for building on Alpine Linux are in the pierce_alpine branch of my fork.

Minimizing Docker Pharo - Plugins

30 November 2019

In the quest^Wrather leisurely ambulation towards the smallest possible Docker image for Pharo for running headless, batch and server-side applications, one approach is to reduce the size of the Pharo VM, by removing irrelevant built-in and external plugins, also known as modules.

Here's what a pharo.cog.spur.minheadless VM built yesterday produces from STON toStringPretty: Smalltalk vm listBuiltinModules:

'[
    ''SqueakFFIPrims'',
    ''IA32ABI VMMaker.oscog-eem.2480 (i)'',
    ''FilePlugin VMMaker.oscog-eem.2530 (i)'',
    ''FileAttributesPlugin FileAttributesPlugin.oscog-eem.50 (i)'',
    ''LargeIntegers v2.0 VMMaker.oscog-eem.2530 (i)'',
    ''LocalePlugin VMMaker.oscog-eem.2495 (i)'',
    ''MiscPrimitivePlugin VMMaker.oscog-eem.2480 (i)'',
    ''SecurityPlugin VMMaker.oscog-eem.2480 (i)'',
    ''SocketPlugin VMMaker.oscog-eem.2568 (i)'',
    ''B2DPlugin VMMaker.oscog-eem.2536 (i)'',
    ''BitBltPlugin VMMaker.oscog-nice.2587 (i)'',
    ''FloatArrayPlugin VMMaker.oscog-eem.2480 (i)'',
    ''FloatMathPlugin VMMaker.oscog-eem.2480 (i)'',
    ''Matrix2x3Plugin VMMaker.oscog-eem.2480 (i)'',
    ''DropPlugin VMMaker.oscog-eem.2480 (i)'',
    ''ZipPlugin VMMaker.oscog-eem.2480 (i)'',
    ''ADPCMCodecPlugin VMMaker.oscog-eem.2480 (i)'',
    ''AsynchFilePlugin VMMaker.oscog-eem.2493 (i)'',
    ''BMPReadWriterPlugin VMMaker.oscog-eem.2480 (i)'',
    ''DSAPrims CryptographyPlugins-eem.14 (i)'',
    ''FFTPlugin VMMaker.oscog-eem.2480 (i)'',
    ''FileCopyPlugin VMMaker.oscog-eem.2493 (i)'',
    ''JoystickTabletPlugin VMMaker.oscog-eem.2493 (i)'',
    ''MIDIPlugin VMMaker.oscog-eem.2493 (i)'',
    ''SerialPlugin VMMaker.oscog-eem.2493 (i)'',
    ''SoundCodecPrims VMMaker.oscog-eem.2480 (i)'',
    ''SoundGenerationPlugin VMMaker.oscog-eem.2480 (i)'',
    ''StarSqueakPlugin VMMaker.oscog-eem.2480 (i)'',
    ''Mpeg3Plugin VMMaker.oscog-eem.2495 (i)'',
    ''VMProfileLinuxSupportPlugin VMMaker.oscog-eem.2480 (i)'',
    ''UnixOSProcessPlugin VMConstruction-Plugins-OSProcessPlugin.oscog-dtl.66 (i)''
]'

And here's the directory listing of the VM as built:

~/src/opensmalltalk-vm/products/ph64mincogspurlinuxht% ls
libAioPlugin.so*             libPharoVMCore.a             libSqueakSSL.so*             libssh2.so@
libCroquetPlugin.so*         libRePlugin.so*              libSurfacePlugin.so*         libssh2.so.1@
libEventsHandlerPlugin.so*   libSDL2-2.0.so.0@            libcrypto.so.1.1*            libssh2.so.1.0.1*
libInternetConfigPlugin.so*  libSDL2-2.0.so.0.7.0*        libgit2.so@                  libssl.so@
libJPEGReadWriter2Plugin.so* libSDL2.so@                  libgit2.so.0.26.8*           libssl.so.1.1*
libJPEGReaderPlugin.so*      libSDL2DisplayPlugin.so*     libgit2.so.26@               pharo*

For server-side applications, a number of the plugins and shared libraries (certainly also libPharoVMCore.a) need not be part of the Docker image.

Minimizing Docker Pharo

11 August 2019

As tweeted: Docker image of Pharo VM, 7.0.3-based app Pharo image, changes/sources files, Ubuntu 16.04, 484MB. With Pharo VM Alpine Docker image, 299MB. Build app Pharo image from minimal, run without changes/sources, Alpine Pharo VM, 83MB!

And here's the Docker container resident set size upon switching from the 484MB Docker image to the Alpine-based Docker image:

Pharo Docker RSS

Norbert Hartl and I are collaborating on minimizing Dockerized Pharo. All are welcome to join.

PoC: Alpine Linux Minimal Stateless Pharo

20 July 2019

Alpine Linux is a security-oriented, lightweight distro based on musl-libc and BusyBox. Official Docker images of Alpine Linux are about 5MB each.

I've successfully built the pharo.cog.spur.minheadless OpenSmalltalk VM on Alpine Linux. Dockerizing the Pharo VM files plus a built-from-source libsqlite3.so (without Pharo image/changes/etc) produces a Docker image weighing in at 12.5MB.

% sudo docker images | egrep "samadhiweb.*alpine"
samadhiweb/pharo7vm                    alpine              299420ff0e03        21 minutes ago      12.5MB

Pharo provides minimal images that contain basic Pharo packages without the integrated GUI, useful for building server-side applications.

From the Pharo 7.0.3 minimal image, I've built a "stateless" image containing FFI, Fuel, and UDBC-SQLite. "Stateless" means the image can be executed by the Pharo VM without the changes and sources files. Here are the sizes of the base minimal image and my SQLite image:

% ls -l udbcsqlite.image Pharo7.0.3-0-metacello-64bit-0903ade.image 
-rw-rw-r-- 1 pierce pierce 13863032 Apr 12 22:56 Pharo7.0.3-0-metacello-64bit-0903ade.image
-rw-rw-r-- 3 pierce pierce 17140552 Jul 20 14:11 udbcsqlite.image

Below, I run the image statelessly on my Ubuntu laptop. Note that this uses the regular Pharo VM, not the Alpine Linux one.

% mkdir stateless
% cd stateless
% ln ../udbcsqlite.image
% chmod 444 udbcsqlite.image
% cat > runtests.sh <<EOF
#!/bin/sh
~/pkg/pharo7vm/gofaro -vm-display-none udbcsqlite.image test --junit-xml-output "UDBC-Tests-SQLite-Base"
EOF
% chmod a+x runtests.sh
% ls -l
total 16744
-rwxr-xr-x 1 pierce pierce      116 Jul 20 15:25 runtests.sh*
-r--r--r-- 3 pierce pierce 17140552 Jul 20 14:11 udbcsqlite.image
% 
%
% ./runtests.sh
Running tests in 1 Packages
71 run, 71 passes, 0 failures, 0 errors.
% ls -l 
total 16764
-rw-r--r-- 1 pierce pierce     6360 Jul 20 15:26 progress.log
-rwxr-xr-x 1 pierce pierce      116 Jul 20 15:25 runtests.sh*
-r--r--r-- 3 pierce pierce 17140552 Jul 20 14:11 udbcsqlite.image
-rw-r--r-- 1 pierce pierce    11072 Jul 20 15:26 UDBC-Tests-SQLite-Base-Test.xml

Dockerizing udbcsqlite.image together with the aforementioned Alpine Linux Pharo VM produces a Docker image that is 46.8 MB in size.

% sudo docker images | egrep "samadhiweb.*alpine"
samadhiweb/p7minsqlite                 alpine              3a57853099d0        44 minutes ago      46.8MB
samadhiweb/pharo7vm                    alpine              299420ff0e03        About an hour ago   12.5MB

Run the Docker image:

% sudo docker run --ulimit rtprio=2 samadhiweb/p7minsqlite:alpine
Running tests in 1 Packages
71 run, 71 passes, 0 failures, 0 errors.

For comparison and contrast, here are the sizes of the regular Pharo 7.0.3 image, changes and sources files:

% ls -l Pharo7.0*-0903ade.* 
-rw-rw-r-- 1 pierce pierce      190 Apr 12 22:57 Pharo7.0.3-0-64bit-0903ade.changes
-rw-rw-r-- 1 pierce pierce 52455648 Apr 12 22:57 Pharo7.0.3-0-64bit-0903ade.image
-rw-rw-r-- 2 pierce pierce 34333231 Apr 12 22:55 Pharo7.0-32bit-0903ade.sources