BEAM Docker Release GitHub Action
GitHub Actions can make CI real easy, and the BEAM docker release action can make a from scratch docker container image of your Erlang/OTP release simple too.
Key takeaways:
- Creates a from scratch container, using a multi-stage, multi-platform from a BEAM release.
- The action supports Elixir with mix; and Erlang/OTP using erlang.mk or rebar.
- Publish images to ghcr.io or any other container registry.
In 2016, I wrote an article about creating erlang releases in docker from scratch. Updating this idea, the BEAM Docker GitHub Release Action integrates easily with your GitHub CI pipeline. It creates a minimal docker image containing only your OTP release and the necessary runtime.
The steps used to prepare a BEAM release into a container:
- All executables are stripped of debug information.
- Shared libraries used by any dependencies are copied into the container.
The same Dockerfile is used by all releases. To ensure
that a shell is not required it uses the exec form of
entrypoint, executing erlexec
directly.
Using Hello World as an example of a BEAM application packaged as a Docker release using a Makefile via erlang.mk. This application has cowboy as a dependency to provide a http endpoint for us to provide the greeting. The application is packaged by relx.
Our GitHub workflow is below. It runs on ubuntu-latest which provides Erlang/OTP for our build. The checkout and build steps are the GitHub standard checkout action followed by make respectfully. The final step is the Beam Docker release action, which taking some parameters so that the image can be stored on the Github Container Registry.
---
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build
run: make
- name: Beam Docker Release
uses: shortishly/beam-docker-release-action@v1.18
with:
registry: ghcr.io
username: $
password: $
On a push
the GitHub workflow will fire logging each part of the
process. On
successful completion the docker image is published to the GitHub
container registry.
To try the container out:
docker run \
--pull always \
--detach \
--publish 8080:80 \
--rm \
ghcr.io/shortishly/hello_world:erlang.mk
The --detach
options tells docker to run the container in detached
mode so that we get a terminal
prompt back, the --publish 8080:80
links port 80 on our hello world
container which cowboy is using to port 8080 on our host. The --rm
deletes the container once we have finished with it.
We can now curl
the container:
curl -i http://localhost:8080/
Which responds with:
HTTP/1.1 200 OK
content-length: 13
content-type: text/plain
date: Sun, 04 Sep 2022 10:41:55 GMT
server: Cowboy
Hello world!
We now have simple BEAM web application built with a GitHub CI Action into a from scratch docker container hosted on the GitHub Container Registry.
Hello World! Simple examples for both Elixir and Erlang can be found at:
Only the release and required runtime shared libraries are present. There is no shell, or any executable other than those required to run the BEAM.
Some real examples:
- Erlang/OTP memcached server and client with some background here.
- Erlang/OTP real-time in memory database replication cache, with a memcached and REST API with some background here.
The parameters used in the BEAM docker release GitHub action can be found here. Some of the ideas are described further in this article with the dependency copying script now written as an escript to support both Erlang/OTP and Elixir. This article looks at using Elixir with the BEAM docker release action.