I’ve been hearing a lot of good things about Elixir lately so I thought of trying it out and making it work with Google App Engine. This post has nothing about these good things though; I’ve been reading and practicing a lot of functional programming lately and I recommend everyone to check it out.

To start, you need to install Elixir. Instructions are described here to set it up. I am running Ubuntu 14.04 so I had to do run these commands:

1
2
3
4
wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo dpkg -i erlang-solutions_1.0_all.deb
sudo apt-get update
sudo apt-get install esl-erlang
sudo apt-get install elixir

Next, I am going to use Phoenix to create a basic web app. To use it, you need to install it as well; instructions are here.

1
2
mix local.hex # install Hex package manager
mix archive.install https://github.com/phoenixframework/archives/raw/master/phoenix_new.ez

Once done, we can start creating Phoenix projects. For our purpose, let’s just create a minimal setup.

mix phoenix.new gaetest --no-brunch --no-ecto

This command will setup a Phoenix project in gaetest. You can run mix phoenix.server inside that directory to run your app. In some cases, you may also need to install Node.

We have to make some config updates to our Phoenix project so we can run it inside GAE. First, add exrm as a dependency. Open mix.exs and add this:

1
2
3
4
5
defp deps do
[{:phoenix, "~> 1.2.0"},
...
{:exrm, "~> 1.0.8"}]
end

Next, we configure our production release to run as a server in port 8080. To do this, open config/prod.exs and change it like this:

1
2
3
4
5
config :gaetest, Gaetest.Endpoint,
http: [port: 8080],
url: [host: "example.com"],
cache_static_manifest: "priv/static/manifest.json",
server: true

Then, onto our GAE setup, we’ll be using a custom runtime as Elixir is not natively supported. We need to install Cloud SDK and Docker for this. Run gcloud init if this is your first time installing Cloud SDK. To make sure everything is ready, run gcloud app –help and docker -v.

Inside the gaetest directory, create app.yaml to configure our project to use a custom runtime:

1
2
3
4
# app.yaml
runtime: custom
vm: true

Next, we’ll create a Dockerfile to describe how to run our app inside GAE. We need to build a release inside our container, hence the mix commands.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Dockerfile
FROM trenpixster/elixir
ENV VERSION 0.0.1
ENV APP_HOST 8080
ENV MIX_ENV prod
EXPOSE $APP_HOST
RUN mkdir /app
COPY . /app/
WORKDIR /app
RUN mix do deps.get, compile
RUN mix phoenix.digest
RUN mix compile
RUN mix release
WORKDIR /app/rel/gaetest/releases/$VERSION
ENTRYPOINT ["./gaetest.sh"]
CMD ["foreground"]

You can use other base Docker images that provide Elixir runtime, I chose trenpixster/elixir for this example but it should run just the same.

Last step is deploying to GAE. If you haven’t created a GCP project yet, you need to create one and get the project ID. You need to have billing enabled in your GCP project to use Flexible Environments. Now run gcloud app deploy --project=PROJECTID --version=VERSION app.yaml to deploy your Elixir app. VERSION is just an arbitrary string. At the end of everything, your app should be available at http://projectid.appspot.com. Enjoy!