I’m trying to produce a minimal docker image for a newly-generated Elixir Phoenix project.
The closure size of my app, like @NobbZ says in the gist discussion, is minimised because only the bits required by the mix release are linked. This is good!
However, when creating a docker image from the results of the mixRelease, the entirety of those dependent nix store derivations are copied into the resulting image. So even with beam_minimal, I get all of erlang, including wx and its extensive HTML documentation.
Is this an expected behaviour, or should I be casting a spell that says “make the docker image smaller”? My approach so far has been to deliberately shrink the size of erlang by using overrides, but it sounds like that’s not the royal path. Even if it was, it’s a fragile approach and means I can’t take advantage of the binary cache.
Any help appreciated! I’m also happy to provide more examples than the ones I spammed onto the gist.
I’ve added another commit that removes runtime_tools from mix.exs as you suggested, but that doesn’t shrink erlang in the docker image. The only remaining reference to erlang-25 in the default package is lib/elixir-1.14.5/ebin/elixir_parser.beam.
The main trick is to use nix why-depends -sSrh on the package closure to figure out why things are needed, then rework the build to strip those. Not on the image because you won’t get an interesting output, but on the package that will be added to the image.
@zimbatm all that why-depends tells me is that elixir wants erlang (I don’t know what you meant by the -sSrh flags as these don’t seem to be flags for why-depends:
Presumably elixir_parser.beam should be referencing something in ERTS? If I delete that file in postInstall I get a very broken app, but no erlang and the container image shrinks massively. I don’t know where in a ‘normal’ mix release the erlang and elixir stuff gets baked into the release, but it seems that when that happens we’re accidentally getting a reference to the full erlang in the nix store from the elixir_parser.
This might be related to beam debug symbol stripping…
I did a PR about that once and another PR changed the default behaviour, though now as you are mentioning this, I remember that it was significant to reduce the closure sizes…
106M container tarball with stripDebug = false
29M container tarball with stripDebug = true
It’s taken weeks to get to the point where mixRelease produces something I can deploy. I guess I’ll work on putting a large notice in the beam languages doc.