zsck

zsck

How much overlap is there between Docker and Elixir (BEAM VM)?

Hello, world!

I have had a question come to mind that I have been hoping some of the enthusiastic folks here in the Elixir community might be able to help me to answer.

Let me preface this by saying that I am a beginner with regards to both Docker and Elixir, and have not worked with Erlang in the past.

As I have been studying Docker recently, I’ve been impressed at how much it is able to do with regards to managing and facilitating communication between images. If we were to think of a running image as a process, then Docker seems to provide a lot of the kinds of concurrent programming superpowers that the BEAM VM does. In particular, I’ve noticed Docker’s ability to run multiple instances of services, easily be configured to monitor for crashes and take care of automatic restarts, and so on. This, it appears to me, seems to overlap greatly with the kinds of things we can do quite easily in Elixir through processes and with things like supervisors.

So my question boils down to this: How much overlap is there really between Docker and the BEAM VM? If I were to try to make a compelling argument to my team that Elixir is a technology worth adopting, considering that no one on my team knows of it and that Docker is already being put to use to varying degrees, what might you say makes it really stand out?

Most Liked

shanesveller

shanesveller

When I use the unadorned word “Docker” below, I’m generally referring to one or all of the Docker daemon, the Docker CLI, or perhaps the Docker image format, and no other additional/adjacent components. If that is not the way OP is using the word Docker, I apologize now.

with regards to distribution, replication, process management, monitoring, and so on.

Strictly speaking, Docker itself as an individual tool doesn’t provide any considerations for these aspects of operating a complex and/or distributed system, without accentuating Docker with still more tools. Kubernetes, Nomad, Swarm, Mesos/DCOS, etc. cover a lot of these functionality gaps with varying approaches.

Distribution: Docker itself is not multi-host aware, and you cannot make it so without layering an orchestration tool on top, such as the aforementioned Kubernetes/Nomad/Swarm. The additional requirements for Swarm are included in most Docker OS packages, but that does not mean that its functionality comes for free or by default. There is no built-in way for container A on host 1 to directly communicate with container B on host 2 with no additional components involved. This concept is supported within the BEAM runtime.

Replication: In order to make sure that X copies of image ABC are running at all times, you need another component. Docker Compose can do some rudimentary scaling of a given container definition to more than one actual running container on a single host, but the Docker daemon itself doesn’t see them as having any direct relationship other than incidental similarities. Docker Compose is not multi-host aware without exporting an app bundle for use with Swarm, or translating to a similar manifest for Kubernetes using something like kompose. AFAIK, this is basically subject to DIY on the BEAM based on how you build your supervision trees, etc. but is not infeasible.

Process Management: This is the one possible exception that Docker itself might provide, depending on on whether you meant management of process groups composed of containers or process groups within single containers. Docker added a minimal --init feature flag for docker run and derived commands, which helps manage child processes within a single container. I believe it uses the semantics of, or directly leverages the code of, tini. It definitely cannot compete with systemd, upstart, runit, supervisord etc. for features or for complexity. More, I would say this functionality does not provide a useful degree of feature parity to process supervision trees in BEAM.

For multiple-container process groups, Docker Compose comes close with the YAML manifest plus a little bit of networking and DNS glue. However, all inter-container communication most go over a shared filesystem or network calls, even if they’re over localhost, crossing various process and memory boundaries. Docker Compose itself is responsible for the creation and “enforcement” of that multi-container environment through its various sub-commands, and the Docker daemon doesn’t have inherent knowledge of those over-arching concerns.

Monitoring: Other than the option to restart exited containers always or under failure conditions, I don’t consider Docker itself to have had meaningful monitoring or supervision behavior for quite a lot of its life as a project. The late introduction of the HEALTHCHECK directive for Dockerfiles did add some better capabilities of self-healing behavior compared to early releases. In Docker, you can’t natively express the idea that when one container exits abruptly, none/one/some/all of its logical siblings should also get restarted, but this is a first-class capability in BEAM.


Docker seems to provide a lot of the kinds of concurrent programming superpowers that the BEAM VM does.

Anything that Docker seems to be able to do with regards to concurrency is probably incidental, and are mostly enabled by the operating system itself, not by Docker. The running containers are just represented as separate OS processes (or process trees) on the host and are subject to the same kernel CPU scheduling as any other program you might run.


I would encourage most newcomers to think of Docker as providing three main value propositions:

  • an extremely portable, straightforward, unsophisticated packaging format for your deliverables
  • a way to (imperfectly) isolate those deliverables from each other while sharing an underlying host
  • a vehicle for abstracting away the differences between different runtime environments and languages

On that last point, Docker doesn’t provide a great abstraction by itself, but by way of example, intentional design of disparate Docker images to have similar “APIs” in the form of their ENTRYPOINT, CMD, etc. can present a unified front in a polyglot organization with applications authored in several different runtime languages.

To come at these points from another angle, operators of software packaged via Docker often only need to care about some limited logistical details:

  • what image and tag to run
  • what CPU/memory resources to allocate
  • what simple arguments to supply
  • what network ports to expose
  • where to expose those ports to

The execution model of the program itself can be a black box. There’s no need for the operator to have much if any knowledge of the implementation language or other “internal” details.

I wouldn’t say any of these three value propositions have direct analogues in the BEAM, and some of them don’t seem to make sense for it anyway.

16
Post #5
sasajuric

sasajuric

Author of Elixir In Action

My impression is that the ecosystem revolving around Docker is indeed used to get the similar features which we get on top of BEAM, such as fault-tolerance and scalability.

To address this, I’ll borrow the example mentioned in another topic:

Imagine that instead of WhicheverLang/Docker/Kubernetes/… you can just do everything in Elixir, running just one OS process per production node. That is vastly simpler than this coctail of technologies. It will simplify all the phases of the software production, such as development, testing, deployment, monitoring of production system, debugging, and let’s not forget about onboarding of new developers which have to learn just one technology to work on any part of the system. That’s a bunch of wins across the board, and for me it’s a big reason why I prefer BEAM facing languages to anything else.

Granted, these other 3rd party technologies are usually more feature rich and advanced, and we often don’t have complete counterparts in the BEAM ecosystem. That said, in my experience, when my needs are simple, I can most often implement a proper solution directly in Elixir, with way less needs to step outside of my main technology, and that ultimately leads to a more technically homogeneous solution, and in turn brings the benefits I mentioned above.

Thus, for me having first class concepts for fault-tolerance and scalability are a must in any runtime I’d consider to power my backend. These properties are needed in any kind of a production server side system, and I want my main technology to be able to help me get there. Without that, we end up improvising on top of inappropriate foundations, which is definitely possible, but will inevitably increase technical baggage and complexity.

15
Post #6
sasajuric

sasajuric

Author of Elixir In Action

Using k8 or anything else for autoscaling is perfectly fine. I’m not necessarily arguing against it, and I also quite like Docker, which we use at my company to bundle our system (and also for our CI tests).

Of course, not everyone needs autoscaling, and therefore not everyone need k8. For example, my first production was working great for a whole year on a small instance, it grew organically, and once we got close to our max capacity, we scaled it manually :slight_smile:

My main point was that it’s my impression that the ecosystem around Docker is often used to get the same features you get natively on top of BEAM. I personally prefer using BEAM without all those other complexities for that, and I feel that for simple to moderately complex scenarios I can get much simpler solution with just BEAM. For more complex cases, I might reach for 3rd party technologies, and I’m certainly not averse to use external products. But since not all scenarios in the system are so extremely complex, in general the technical solution built on top of BEAM is in my opinion much simpler compared to most other languages, especially the ones which don’t offer proper actor-like lightweight concurrency and first-class fault tolerance.

OvermindDL1

OvermindDL1

BeamVM allows introspection and tracing at a very detailed level compared to what docker can do, which can only get to OS process level. Docker doesn’t really distribute or replicate though tools built on it might do that.

ibgib

ibgib

I have gone down the road of both Elixir and the Docker ecosystem, which includes Swarm (though Swarm not implemented yet, only Docker Compose with multiple services and using Docker machine for deployment). Here are my thoughts on the dynamics:

  • Docker, and in particular Docker Swarm, is for macroscopic “processes”
    • Has durable processes, like BEAM supervision trees, for restoring or adding nodes in a known state but relatively expensive to bring up.
    • Think 10s, 100s, or maybe 1000s of processes.
    • Has better isolation WRT inter-nodal security
      • “Harder” to escape a container than a connected BEAM process to influence other processes.
  • Elixir is for microscopic processes
    • Extremely lightweight parallel processes, even lighter than threads, which are super cheap.
    • Global inter-process communication.
    • Think 1000s, 10000s, or 1000000s+ of processes.

Where Next?

Popular in Questions Top

Tee
can someone please explain to me how Enum.reduce works with maps
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
mathew4509
I have a list say x = ["23gh", "56kh", "97mh"] I would like to pass each element to Val in each iteration. Say, in iteration 1 -------...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 49522 488
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New

We're in Beta

About us Mission Statement