BEAM Docker Release GitHub Action

2 minute read

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:

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:

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.