Using rebar3 with Docker

I prefer to avoid installing dev tools on my laptop. I used to create a separate Vagrant instance for each project, but using Docker should provide a lighter weight alternative.

Assuming you already have the Docker tooling installed, the first thing to do is download the base container:

docker pull erlang

Next, download the latest rebar3 binary:

curl -OL https://s3.amazonaws.com/rebar3/rebar3 && chmod +x ./rebar3

At this point, you’re ready to create the app skeleton:

docker run --name $APP_NAME -it --rm -v ${PWD}:/app -w /app erlang ./rebar3 new app $APP_NAME

Annoyingly, rebar assumes that it should create the folder for the project, so you’ll need to move all the generated files up a level (or put up with an extra subdir). Also, the generated files are owned by root, so you probably want to chown the entire dir.

If you’re going to use any rebar plugins, you probably want to put it’s cache dir somewhere that will survive container restarts. Add this to your rebar.config:

{global_rebar_dir, "/app/.cache"}.

And then you can compile your app:

docker run --name $APP_NAME -it --rm -v ${PWD}:/app -w /app -e REBAR_CACHE_DIR=/app erlang ./rebar3 compile

SSH keys in Docker

One of the first stumbling blocks, when using Docker, is often discovering that your SSH keys are on the wrong side of the hatchway.

A simple solution is just to copy them, when building the image:

COPY ~/.ssh /root/.ssh

And this is reasonable, if the image is never going to leave your laptop. Any respectable tinfoil hat wearing neckbeard will look for an alternative though.

An obvious next step is to mount the same folder, as a volume:

SSH=~/.ssh
docker run -it --rm -v ${SSH}:/root/.ssh app npm install

Unfortunately, you’ll probably find at this point that the permissions are not correct inside the container, and that if you try and change them, they are hopelessly entangled with the permissions outside the container.

After much googling, and trying ideas from StackOverflow, the best solution I found was to use the same ssh-agent as the host:

SSH=~/.ssh
docker run -it --rm -v ${SSH}:/root/.ssh -v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent app npm install

(I’m still mounting the .ssh folder, but only to recycle my known_hosts file).

Or, using compose:

version: '2' 
services:
  app:
    build: .
    volumes:
      - .:/app
      - ~/.ssh:/root/.ssh
      - $SSH_AUTH_SOCK:/ssh-agent