Erlang and Elixir in AWS Lambda using Container Images (part 1)
AWS recently announced container image support for AWS Lambda Functions, allowing you to run your Lambda functions in a custom Docker image that you supply. This opens up a wide variety of new possibilities for Lambda, including:
- Runtime libraries pre-loaded in Lambda, reducing the need to package libraries with code
- Test Lambda functions locally, in a near-identical containerized environment
- Write Lambdas in any language you want
It is the third bullet point that I wish to explore in this series. Erlang and Elixir, two functional programming languages designed to support high-concurrency programming, based on technology that is well known for its ability to produce programs with a high degree of fault-tolerance and availability, are, to my mind, well-suited to the serverless model.
In this series I will go through the steps of building a containerized, highly concurrent application in Erlang and Elixir, containerizing the application for portability, making the container compatible with AWS Lambda, and finally, converting the code to be deployable to AWS Lambda, thus decoupling it from the container.
Creating the Docker Container
First things first — we will need a container to run all this stuff in. Containers make it very easy to distribute the runtime environment of your application, allowing other developers of your project to be up and running in minimal time.
This tutorial assumes that you have Docker installed.
To begin, we create our project directory:
mkdir erlambda
cd erlambda
Then we create a file named Dockerfile
in the directory:
FROM public.ecr.aws/amazonlinux/amazonlinux:latest
RUN yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y
RUN yum install https://packages.erlang-solutions.com/erlang-solutions-2.0-1.noarch.rpm -y
RUN sed -i.bak "s/\$releasever/7/" /etc/yum.repos.d/erlang_solutions.repo
RUN yum install erlang elixir -y
CMD [ "/usr/bin/env", "bash" ]
Finally, we build and run our image:
docker build -t erlambda .
docker run -it erlambda
The first time you run docker build
, it will take a few minutes to create the new image. Future runs are sped up considerably as it is not necessary to re-install the necessary packages. This will build the image and launch the container, and present you with a root-privileged command prompt inside the container:
bash-4.2#
You may use the commands erl
and iex
to verify that Erlang and Elixir are available to you. When you are done, type:
exit
and your container will be stopped; you will be returned to the command prompt. Hooray, your image is ready!
Erlang and Elixir Hello World
OK, now we have to write some code that actually uses this container. Time to write our obligatory `Hello, World` one-off that tests that we’re actually up and running.
Create a directory named src
and add the file hello.erl
to it, with the following contents:
-module(hello).
-export([hello_world/0]).
hello_world() -> io:fwrite("Hello, World, from Erlang!\n").
Next, edit Dockerfile
and replace the last line with:
COPY src /src
WORKDIR /src
RUN erl -compile hello
CMD erl -noshell -s hello hello_world -s init stop
Finally, rebuild and rerun the container from the command line:
docker build -t erlambda .
docker run erlambda
If all goes well, you should see the output Hello, World, from Erlang!
in your terminal.
Next, we want to test Elixir in the same container. Create a file hello_elixir.exs
in your src
directory with the following contents:
require :hello
IO.puts("Hello, World, from Elixir!")
:hello.hello_world()
Notice that this script imports the hello
Erlang module defined above.
Next, update the last two lines of your Dockerfile
(the RUN
and CMD
lines) to this:
RUN erl -compile hello
CMD elixir hello_elixir.exs
Repeatedly running the build and run docker commands is already becoming burdensome, so let’s extract that into run.sh
:
#!/usr/bin/env bash
docker build -t erlambda .
docker run erlambda
Then run:
chmod +x run.sh
./run.sh
This should be your output:
Hello, World, from Elixir!
Hello, World, from Erlang!
In almost no time, we have created a Hello, World application utilizing Docker, Elixir, and Erlang. Pat yourself on the back, then spend some time playing with the Docker container, and the Erlang and Elixir code. Finally, buckle in for the sample application, which we will begin making in part 2.
Learn Docker: https://www.docker.com/101-tutorial
Learn Elixir: https://elixirschool.com/en/
Learn Erlang: https://learnyousomeerlang.com/