如何配置Docker以公开Erlang节点?

4dc9hkyq  于 2022-12-08  发布在  Erlang
关注(0)|答案(1)|浏览(151)

我写了一个简单的docker映像,它启动了一个Erlang节点(rebar3版本,console启动模式)。它启动得很好,让我可以从容器内部ping节点。但是,我不能让erl shell从hostping它-它只是返回pang,并且在dockerized控制台中没有记录任何内容。
Dockerfile只是启动节点,并不执行任何更有趣的操作。

清单
  • Cookie已设置并匹配
  • 在两个节点上都设置了sname
  • 可从其他容器节点访问Docker节点
  • 我使用完整的sname引用Docker节点(尝试了nodename@localhostnodename@machinenamenodename@127.0.0.1
  • epmd端口已暴露(也尝试不使用它)

我忘了什么才能让它工作呢?

ui7jx7zq

ui7jx7zq1#

    • 免责声明:**此答案适用于Linux系统。另外,我认为第一个和最后一个选项是最简单的

有几种方法可以做到这一点,但在此之前,让我们先设定一些关键的想法:
1.下面的脚本在docker内部运行,模拟一个节点,它只是等待一个节点连接,打印它并终止。

SCRIPT_RUN_IN_DOCKER='ok = net_kernel:monitor_nodes(true), fun F() -> receive {nodeup, N} -> io:format("Connected to ~p~n", [N]), init:stop() end end().'

1.为了使分发协议成功,不仅需要以用于ping的名称到达节点,而且整个节点名称都必须匹配。

  1. Erlang的-node可以与IP一起使用,它将广泛用于以下命令

选项

现在,让我们来看看选项(所有命令都将在不同的终端中运行)

Docker:主机网络命名空间

当在host的网络名称空间(--net=host)中启动docker时,这与在docker外部运行两者没有区别(出于网络目的)。

    • 名称(ip):
$> docker run --net=host erlang erl -noinput -name foo@127.0.0.1 -setcookie cookie -eval $SCRIPT_RUN_IN_DOCKER
 Connected to 'bar@127.0.0.1'

 $> erl -noinput -name bar@127.0.0.1 -setcookie cookie -eval "net_adm:ping('foo@127.0.0.1'), init:stop()."
    • sname与@本地主机:
$> docker run --net=host erlang erl -noinput -sname foo@localhost -setcookie cookie -eval $SCRIPT_RUN_IN_DOCKER
 Connected to bar@localhost

 $> erl -noinput -sname bar@localhost -setcookie cookie -eval "net_adm:ping('foo@localhost'), init:stop()."
    • sname与@$(主机名-f):
$> docker run --net=host erlang erl -noinput -sname foo -setcookie cookie -eval $SCRIPT_RUN_IN_DOCKER
 Connected to 'bar@amazing-hostname'

 $> erl -noinput -sname bar -setcookie cookie -eval "net_adm:ping('foo@$(hostname -f)'), init:stop()."

Docker:使用Docker的默认网桥(docker0

默认情况下,Docker在自己的桥中启动容器,这些IP不需要公开任何端口就可以到达。
ip a show docker0 lists 172.17.0.1/16 for my machine, and erlang listens in 172.17.0.2 (shown in docker inspect <container> )

    • 名称(ip):
$> docker run erlang erl -noinput -name foo@172.17.0.2 -setcookie cookie -eval $SCRIPT_RUN_IN_DOCKER
 Connected to bar@baz

 $> erl -noinput -name bar@baz -setcookie cookie -eval "net_adm:ping('foo@172.17.0.2'), init:stop()."
    • sname(解析为容器IP的假名称):
# The trick here is to have exactly the same node name for the destination, otherwise the distribution protocol won't work.
 # We can achieve the custom DNS resolution in linux by editing /etc/hosts

 $> tail -n 1 /etc/hosts
 172.17.0.2 erlang_in_docker

 $> docker run erlang erl -noinput -name foo@erlang_in_docker -setcookie cookie -eval $SCRIPT_RUN_IN_DOCKER
 Connected to 'bar@amazing-hostname'

 $> erl -noinput -sname bar -setcookie cookie -eval "net_adm:ping('foo@erlang_in_docker'), init:stop()."

Docker :使用其他 Docker 桥
只需创建新网络并使用新网络中的ips重复前面的步骤即可

docker network create erlang_docker_network
docker inspect erlang_docker_network

Docker:暴露带有两个EPMD的端口

当暴露端口时,您必须同时处理端口和ip,因为EPMD端口必须相同。
在这种情况下,您将有两个epmd,一个用于主机,另一个用于容器(EPMD拒绝来自非本地对等体的名称请求),监听同一个端口号。
这里的技巧是(ab)使用127.0.0. * ips,这些ips全部指向localhost来模拟不同的节点。

    • 名称(ip):
$> epmd -address 127.0.0.1

 $> docker run -p 127.0.0.2:4369:4369/tcp -p 127.0.0.2:9000:9000/tcp erlang erl -noinput -name foo@127.0.0.2 -setcookie cookie -kernel inet_dist_listen_min 9000 -kernel inet_dist_listen_max 9000 -eval $SCRIPT_RUN_IN_DOCKER
 Connected to bar@baz

 $> erl -noinput -name bar@baz -setcookie cookie -eval "net_adm:ping('foo@127.0.0.2'), init:stop()."
  • -sname (fake name resolving to 127.0.0.2)
And here we need again the DNS resolution provided by /etc/hosts

 $> tail -n 1 /etc/hosts
 127.0.0.2 erlang_in_docker

 $> epmd -address 127.0.0.1

 $> docker run -p 127.0.0.2:4369:4369/tcp -p 127.0.0.2:9000:9000/tcp erlang erl -noinput -name foo@erlang_in_docker -setcookie cookie -kernel inet_dist_listen_min 9000 -kernel inet_dist_listen_max 9000 -eval $SCRIPT_RUN_IN_DOCKER
 Connected to bar@baz

 $> erl -noinput -sname bar@baz -setcookie cookie -eval "net_adm:ping('foo@erlang_in_docker'), init:stop()."

坞站合成

docker-compose允许您轻松设置多容器系统。使用它,您无需创建/检查网络。
给定以下docker-compose.yaml

version: '3.3'

services:
  node:
    image: "erlang"
    command:
      - erl
      - -noinput
      - -sname
      - foo
      - -setcookie
      - cookie
      - -eval
      - ${SCRIPT_RUN_IN_DOCKER} # Needs to be exported
    hostname: node

  operator:
    image: "erlang"
    command:
      - erl
      - -noinput
      - -sname
      - baz
      - -setcookie
      - cookie
      - -eval
      - "net_adm:ping('foo@node'), init:stop()."
    hostname: operator

如果运行以下docker-compose run命令,您将看到结果:

$> docker-compose up node
Creating network "tmp_default" with the default driver
Creating tmp_node_1 ... done
Attaching to tmp_node_1
node_1      | Connected to baz@operator
tmp_node_1 exited with code 0

$> docker-compose run operator

相关问题