Statically Compile Crystal Program and Distribute as docker Image
In this article we are sharing how to statically compile a crystal program and then share the executable inside a docker image. We will create the smallest docker image possible. Smaller images are easier to manage, distribute and boot.
Note: The way docker works, each command/line creates a layer (with context).
The good news about crystal lang is the they distribute the docker image with all the libraries so that we can build static compiled executable(s). Attaching the docker file I wrote to statically compile a crystal language program.
Note: The program uses the Kemal web framework, so this could also be considered an article on how to statically compile and distribute a kemal web app.
|
|
We are using the crystal lang alpine build image. This is an image release/updated by the crystal team when they release a new version. Alpine linux is the smallest base image available for docker, we will be using this as our base image as well.
We are also using multi-stage docker build. We are compiling our code in crystallang/crystal:1.0.0-alpine-build
then moving to alpine:latest
. Hence our final image will be small, with nothing more than the required executables.
Now explaining each part one by one:
Base Image
|
|
Our project uses yaml and sqlite, so we need to make sure there static libraries are present in our image or we won’t be able to compile.
Caching the dependency installer
|
|
We are installing the shards in a prior step to ensure that docker caches it. After which we copy the assets (html/css/js) required by the final build.
To create statically compiled executable we just need to pass the flag, and the compiler we statically link the required libraries.
Static Compile the executable
|
|
Final Image
|
|
Finally we created the final image with a plain alpine:latest
image, without any of the extras. Just copying the required executables and then exposing the port our app is running on.
In our case the final image was 78 MB.