Anyone experimented with Erlang/OTP as PID=1 in a Linux container?

Has anyone experimented with Erlang/OTP as PID=1 in a Linux container?


Also interested on this. My Erlang releases inside docker have PID=42.

1 Like

It’s not exactly erlang, but i think that the nerves project uses this approach.
They boot a linux kernel, and instead of init or systemd have a elixir process with pid 1.

1 Like

It’s my understanding that it’s a bad idea: [erlang-questions] Lots of epmd in pod

Essentially, init (pid=1) processes are supposed to (among other things) reap zombies. I don’t think Erlang knows to do that.

At least, it didn’t. That might have changed.

1 Like

It was fixed in Erlang/OTP 23.


Cool. So there’s no problems using a BEAM as init/PID1?

1 Like

Not that I know of, but there are a lot of things that I don’t know :slight_smile:


That’s not exactly correct. They do use GitHub - nerves-project/erlinit: Replacement for /sbin/init that launches an Erlang/OTP Release, which then in turn starts the erlang vm.

1 Like

I made it work, but it uses quite an array of undocumented internals. Don’t want to dive in gory details, but what you’re looking for is a way to run beam.smp (or beam.frmptr.smp, or your other favourite flavour) set up with a bunch of environment variables.
I have a blogpost that enumerates some of these. It is however not something I’d recommend outside of debugging purposes. But if you don’t mind reading code (instead of OTP documentation), it works great.

1 Like

Thank you all for your responses :heart: I’ll look into Nerves and @max-au variant.

Hey @max-au
Couldn’t find anything related to PID=1 in your blog post.

If you want to run the process with PID=1, you need to run beam.smp binary (because that’s the actual executable, all other scripts are trampolines). That post explains some internals that allow you to run beam.smp.

Under Docker, my release is started using foreground option (generated by rebar3):

        exec "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
            -boot "$BOOTFILE" -mode "$CODE_LOADING_MODE" \
            -boot_var SYSTEM_LIB_DIR "$SYSTEM_LIB_DIR" \
            -config "$RELX_CONFIG_PATH" \
            -args_file "$VMARGS_PATH" \
            $EXTRA_DIST_ARGS -- "$@"

I was expecting $BINDIR/erlexec (which is a binary) to be the final executable replacing the current bash process (thanks to exec). All these should have produced a PID=1, but it isn’t the case. I always get PID=42 for my erlang releases.

@max-au is there a way to run my release using beam.smp instead and setting couple of ENV variables?

That’s exactly what the blog post explains. Long story short (BINDIR must be set to location of beam.smp):

export BINDIR=/app/otp/bin
/app/otp/bin/beam.smp -- -root /app/otp/ -bindir /app/otp/bin

So, 3 things must be set:
BINDIR environment variable pointing at the folder with ERTS binaries (e.g. beam.smp).
-root command line argument pointing at the folder where your release resided (normally contains folders like bin and lib)
-bindir command line pointing at the same folder as BINDIR