uhlenheuerdotnet
programming, .NET, linux and others

Running ejabberd in docker using god

by Gregor Uhlenheuer on December 13, 2014

Lately I have been doing some experiments using ejabberd with docker. In order to control the running ejabberd instance inside the container it is good to have some kind of supervising daemon. Possible candidates I tried so far are supervisord and god.

god

The latter is my preferred choice as it supports very nice process supervisioning using a linux kernel userspace interface (you will need your kernel to be compiled with CONFIG_CONNECTOR for this mechanism to work). That way there is no need to poll the process if it is still running. Moreover god comes with a lot of reasonable default preferences resulting in very simple configuration files. A basic god configuration file might look something like this:

God.watch do |w|
  w.name = "ssh"
  w.start = "/usr/sbin/sshd -D"
  w.keepalive
end

ejabberd

Sadly using ejabberd using god is not as easy as the example shown above. god expects the process to supervise to run in the foreground whereas ejabberd which is usually controlled by the ejabberdctl script starts a background daemon process.

I extracted some of the logic in the ejabberdctl script into a god configuration file that works with god as expected:

HOST         = 'localhost'
NAME         = "ejabberd@#{HOST}"
SPOOL_DIR    = '/var/lib/ejabberd'
EJABBERD_DIR = '/lib/ejabberd'
LOG_DIR      = '/var/log/ejabberd'
LOG_FILE     = "#{LOG_DIR}/ejabberd.log"

OPTS   = '+K true ' +    # kernel polling
         '-smp auto ' +  # automatic SMP detection
         '+P 250000'     # 250,000 ports

KERNEL = '-kernel inet_dist_use_interface \{0,0,0,0\}'
SASL   = "-sasl sasl_error_logger \\{file,\\\"#{LOG_FILE}\\\"\\}"

ERL    = "erl -noinput " +
         "-sname #{NAME} " +
         "-pa #{EJABBERD_DIR}/ebin " +
         "-mnesia dir \"'#{SPOOL_DIR}'\" " +
         "#{KERNEL} " +
         "-s ejabberd #{OPTS} #{SASL}"

CMD    = "erl -noinput -hidden " +
         "-sname ctl_#{HOST} " +
         "-pa #{EJABBERD_DIR}/ebin " +
         "#{KERNEL} " +
         "-s ejabberd_ctl -extra #{NAME}"

#
# EJABBERD
#
God.watch do |w|
    w.name = 'ejabberd'
    w.dir = SPOOL_DIR
    w.env = {
        'EJABBERD_CONFIG_PATH' => '/etc/ejabberd/ejabberd.yml',
        'EJABBERD_LOG_PATH'    => LOG_FILE
    }

    w.start   = "#{ERL} start"
    w.stop    = "#{CMD} stop"
    w.restart = "#{CMD} restart"

    w.grace = 20.seconds
    w.keepalive
end

docker

Now you just have to add the god configuration to your Dockerfile like this:

RUN gem install god

ADD ./config.god /config.god

CMD ["god", "-c", "/config.god", "-D"]

This post is tagged with ejabberd, docker, god, container and linux