Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
The docker platform has been around for a couple of years already, so letâs briefly review which benefits it provides, and why you should consider using it:
An easy means to boot your production services on the desktop
I still remember how complex it was to bring up MySql on OS X in the past. But it would be even worse if you consider a scenario where your production environment is running some specific version of MySQL, especially built on non OSÂ X.
How would you bring that up? Luckily this problem just goes away when youâre using docker, as you can bring up any version of program as easily as executing the command docker run mysql:5.3.
The ability to work against a realistic testing environment, without having to implement service mocks
It was always an issue. If you wanted to test your software properly, you had to bring up (or mock) a lot of related services. And it always created issues, as a mock never really matches the characteristics of a complete running service.
And with docker you can just plug any software that your application relies upon, and have it right there as a part of your testing environment.
Creating realistic cloud infrastructure, using containers
Finally, docker containers can be spun up by tools like Apache Mesos forming full featured clouds, deployable in the effortless and clear manner, and incredibly stable!
Interested? Lets see which benefits the technology can give you when it comes to the Erlang and Elixir worlds.
Testing distributed erlang applications with docker
Letâs consider a case when we need to create and test a distributed erlang application, running on the same machine, and letâs say we want to have it running, but it relies upon some extra services.
This kind of setup can be described in the following docker-compose file:
version: "3"services: c1: image: erlang:latest # We're using the following command to bring up erlang shell # for the example purposes, but in the other case the command # will describe a running container command: erl -noshell -name app@host1.com -setcookie cookie container_name: host1.com networks: - net1 c2: image: erlang:17.5 command: erl -noshell -name app@host2.com -setcookie cookie container_name: host2.com networks: - net1 ejabberd: image: rroemhild/ejabberd ports: - 5222:5222 - 5269:5269 - 5280:5280 container_name: host3.com environment: - ERLANG_NODE=ejabberd@host3.com - XMPP_DOMAIN=test.io - ERLANG_COOKIE=cookie - EJABBERD_ADMINS=admin@test.io - EJABBERD_USERS=admin@test.io:admin - EJABBERD_SKIP_MODULES_UPDATE=true networks: - net1# We're using custom network setup, as it ships with a DNS# system which allows containers to communicate by hostnames.networks: net1: driver: bridge
Now letâs boot this setup and take a look at how we can facilitate communication between these containers:
- Bring up every container described in the file: docker-compose up -d
- Connect to one of the hosts: docker exec -it host2.com erl -name test@host2.com -setcookie cookie -remsh app@host2.com
- Verify that host connectivity is functioning correctly:
(app@host2.com)1> net_adm:ping('app@host2.com').pong(app@host2.com)2> net_adm:ping('app@host1.com').pong(app@host2.com)4> net_adm:ping('ejabberd@host3.com').pong(app@host2.com)5> nodes().['test@host2.com','app@host1.com','ejabberd@host3.com']
In this simple example weâve brought up several containers and connected them using the standard erlang distribution. This is possible because all of the containers are running in the same docker network, and can access one anothers epmd daemonsâŠ
But how can we connect docker containers running on different hosts?
Connecting beams running on separate machines
Finally if you want to go to production, and to create a real cloud, running multiple hosting machines, the setup above will not work, as containers will not know how to connect to each other.
Indeed, hosts will not be aware about each others docker networks (in reality some work to interconnect docker containers using docker swarm or amazon ec2 containers service is being done, but we could not bring it up reliably running), and we would have to organise a more complex connection mechanism.
Actually the idea of creating alternative erlang distribution protocol came out of this amazing article, Erlang (and Elixir) distribution without epmd, we just decided to make few steps forward to create a pluggable application, which would just âFind them all, chain them all and⊠make sure all of them are always connected.â
The epmdless approach
As itâs described by Magnus Henoch, in his blog post, the epmd is not really needed in the dockerised setup, as docker environment is already forcing to expose particular ports for external access. And because of that there could be only one port used by erlang distribution (as other ports just will not be exposed).
On the other hand itâs quite easy to store mapping between hosts and ports inside the Erlang application. And now we already have the application for that: EpmdLess (credits go to Dmitry Mazurin for building itâs initial version).
Lets now see how it works:
- Clone out Erlang Distribution in Docker SandBox Applucation: git clone https://github.com/oltarasenko/erlang_distribution_in_docker.git
- Checkout to epmdless_example branch: git checkout epmdless_example
- Build docker image for the application: cd erlang_distribution_in_docker && docker-compose build
- Bring up the containers described in docker-compose.yml: docker-compose up
- Letâs check that epmd is not really running on the nodes:
docker-compose exec app1 lsof -i -n -PCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEbeam.smp 1 root 13u IPv4 251627 0t0 TCP *:17012 (LISTEN)
- Login to one of the containers: docker-compose exec app3 _build/default/rel/sample_app/bin/sample_app console
- Connect to another node using epmdless:
> epmdless_dist:add_node(âapp1@host1.comâ, 17012). % Add node into epmdless database> net_adm:ping(âapp1@host1.comâ). % Do ping> nodes(). % Node is discovered
Here is the short video showing steps above executed:
Great, as you can see weâre able to connect nodes this way. Hovewer it looks like it would be quite hard to discover nodes this way, as we would need to initiate epmdless_dist:add_node and net_adm:ping calls for every node. Thatâs why we also want to suggest a convenient way (at least we hope you will like it) which allows you to also enable automatic node discovery for docker platformâŠ
Nodes discovery on a distributed cluster
In order to be able to organise node discovery process weâve released the Erlang Node Discovery application which automatically establishes connections between different nodes, as itâs specified in the application configuration file.
Besides this, it provides a simple API that allows you to extend the node discovery mechanism and to consume data from any other node/port database (local file, redis, database, etc).
{ erlang_node_discovery, [ % epmdless_dist as our database {db_callback, epmdless_dist}, {hosts, ["host1.com", "host2.com", "host3.com"]}, % query following appnames/ports {node_ports, [ {'app1', 17012}, {'app2', 17013}, {'app3', 17014} ]} ]}
This application will now spawn a process per possible pair of {appname@hostname, port} and will try to organise a fully connected cluster (and will do the reconnection).
In our case (as defined in configuration file above) it will spawn processes for the following possible nodes:
app1@host1.com:17012 app2@host1.com:17013 app3@host1.com:17014 app1@host2.com:17012 app2@host2.com:17013 app3@host2.com:17014 app1@host3.com:17012 app2@host3.com:17013 app3@host3.com:17014
Letâs give it a try:
- Clone out Erlang Distribution in Docker SandBox Applucation: git clone https://github.com/oltarasenko/erlang_distribution_in_docker.git
- Checkout to master branch (needed in case youâve already cloned everything on previous step): git checkout master
- Build docker image for the application: cd erlang_distribution_in_docker && docker-compose build
- Bring up the containers described in docker-compose.yml: docker-compose up
And again, here is a video summarising the steps above:
Ok, but what about Elixir?
Actually there is no problem re-using the same erlang libs to run a connected elixir cluster. The only trick is to show elixir where to find erlang libs :). This time Iâve added a Makefile to demonstrate it.
start: @ERL_LIBS=_build/dev/lib/ iex --name ${NODE_NAME} \ --erl "+K true" \ --erl "-config config/sys.config" \ --erl "-proto_dist epmdless_proto" \ --erl "-start_epmd false" \ --erl "-epmd_module epmdless_client" \ -S mix
Letâs now review the Elixir example:
- git clone https://github.com/oltarasenko/epmdless.git
- docker-compose build
- docker-compose up
Thatâs all. Here is the short video demonstration!
Originally published at www.erlang-solutions.com.
Running distributed Erlang & Elixir applications on Docker was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.