Rabbitmq: Rabbitmqctl hangs when run via container

Created on 13 Feb 2016  路  4Comments  路  Source: docker-library/rabbitmq

While poking the official rabbitmq container (3.6.0: 6c1bb940499a) I've noticed that I cannot easily run rabbitmqctl. When I attempt to pass rabbitmqctl as the container command it hangs:

$ docker run --rm -ti rabbitmq rabbitmqctl
<Several seconds pass, hit ctrl-c>
^C
BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
       (v)ersion (k)ill (D)b-tables (d)istribution
a

The BREAK appears to be coming from erlang. I've tried several combinations of options which all hang:

  • default entrypoint, /usr/lib/rabbitmq/bin/rabbitmqctl command
  • /usr/lib/rabbitmq/bin/rabbitmqctl entrypoint
  • /bin/bash entrypoint, /usr/lib/rabbitmq/bin/rabbitmqctl command

/bin/bash entrypoint, rabbitmqctl command fails slightly differently with an error about being unable to open ./rabbitmq-env, but I believe that's unrelated.

Interestingly, though, if I enter the container with a command of /bin/bash and run rabbitmqctl interactively it works. I haven't yet found what the differentiating factor is.

This is currently a blocker for me for using the official container as I need to be able to wrap rabbitmqctl for use outside the container. I wish to run Rabbit in a container but need rabbitmqctl to work from the host both for a management tool which assumes rabbitmqctl is installed locally. My intention is to wrap a command similar to the docker run above in a script which sets the node and erlang cookie.

EDIT: One of the cases I'd marked has hanging fails differently.

Most helpful comment

This is a hacky workaround: docker run -it --rm --link some-rabbit:my-rabbit -e RABBITMQ_ERLANG_COOKIE='secret cookie here' rabbitmq:3 bash -c 'rabbitmqctl -n rabbit@my-rabbit list_users && true'. My best guess is that the /usr/lib/erlang/erts-7.2/bin/beam.smp process tries to kill itself with a sigint but since it is pid 1 when bash is not there, it just stays alive indefinitely.

All 4 comments

This is a hacky workaround: docker run -it --rm --link some-rabbit:my-rabbit -e RABBITMQ_ERLANG_COOKIE='secret cookie here' rabbitmq:3 bash -c 'rabbitmqctl -n rabbit@my-rabbit list_users && true'. My best guess is that the /usr/lib/erlang/erts-7.2/bin/beam.smp process tries to kill itself with a sigint but since it is pid 1 when bash is not there, it just stays alive indefinitely.

Thanks, that worked. In case others find it useful I've settled on this script do have the rabbitmqctl command on the host operate against the container:

#!/bin/bash
#
# rabbitmqctl helper: Helper script to run rabbitmqctl against the Rabbit container

# Use the similar longname logic as out of the container starter script
# https://github.com/docker-library/rabbitmq/blob/d9c4635649edacf6728bd2a28aedc97c77ac47f9/docker-entrypoint.sh#L15-L18
if [ "$(hostname -f)" != "$(hostname -s)" ]; then
    LONGNAME_VAR="RABBITMQ_USE_LONGNAME=true "
else
    LONGNAME_VAR=""
fi

# Command hackiness via https://github.com/docker-library/rabbitmq/issues/68
# Command variable required to make back handle arguments and quoting correctly.
COMMAND="${LONGNAME_VAR}/usr/sbin/rabbitmqctl"

# The following is lifted off https://github.com/rabbitmq/rabbitmq-server/blob/aae969130172ec5afc98a391f6f66a14cdd0a853/packaging/common/rabbitmq-script-wrapper
for arg in "$@" ; do
    # Wrap each arg in single quotes and wrap single quotes in double quotes, so that they're passed through cleanly.
    arg=`printf %s "$arg" | sed $SED_OPT -e "s/'/'\"'\"'/g"`
    COMMAND="${COMMAND} '${arg}'"
done
COMMAND="${COMMAND} && /bin/true"

#echo "\"$COMMAND\""

# This uses an exec as rabbitmq-plugins needs filesystem access.
#   As an exec generally works better than a separate container
#   (no cookie, hostname, or erlang issues) it was picked as the path of least resistance.
# No sudo: restrict to root/docker admins
docker exec RabbitMQ bash -c "$COMMAND"
exit $?

Notes:

  • The LONGNAME_VAR is to get it working with both short and long hostnames (test kitchen uses short hostnames but we're using long in prod.)(rabbitmq-server #613) This wouldn't be required if I was running a container with the entrypoint script instead of using an exec.
  • The 'for arg in "$@"' block ensures '*' is handled correctly when setting vhosts
  • I opted for an exec as I'm also using this script (via a chef template) to also drive rabbitmq-plugins which needs to write /etc/rabbitmq/enabled_plugins. As I've already decided only to support one rabbit container on a host this seemed cleaner than -n (which has it's own messiness) and volume mounts.

Also note that '-n rabbit@my-rabbit' doesn't work as the hostname has to match for erlang distribution to work. So if you link in as suggested you have to link as the hostname of the rabbit container. Erlang distribution, in my opinion, is ... fussy.

Erlang is not suited to work as pid 1 because it can't handle exits of processes it didn't start. Detailed discussion is at http://erlang.org/pipermail/erlang-questions/2015-December/thread.html#87141
bash process mentioned above just reserves pid 1 for itself, and erlang can happily work in this circumstances.

This looks like it was solved. Closing old issue.

Was this page helpful?
0 / 5 - 0 ratings