As part of an internal migration of our XMPP server, we thought this would also present a good opportunity to test drive Docker to see if it would be useful for other infrastructure projects in the future. Docker is fast becoming the industry standard for deployment on Linux platforms, and for a number of good reasons:
* Very lightweight, unlike conventional virtual machines
* Good isolation between multiple containers running on the same host machine
* Allows for multiple applications that rely on different versions of the same package to run on the same box
* Provides repeatability in deployments
For this example, we’ll be looking to Dockerise the Prosody XMPP server, with a PostgreSQL backend. If you are completely new to Docker, it would be useful to read the official documentation first to familiarise yourself with the basic concepts.
To start with, we’ll consider the PostgreSQL side, which will be split amongst two containers. One container will contain the application software (version 9.3 in this case), while the second will simply provide a container for persisting data. This means the first container can be swapped at a later time (to upgrade to a later Postgres version for example), while retaining the database data in the second container (which is quite desirable).
For the data container, the Dockerfile is specified as follows:
This uses the very lightweight busybox base image, which provides a minimal set of userland software, and exposes a volume for writing to at
/data. Two files with the Postgres configuration settings are also added to this directory, which can be picked up by the application container later, allowing the application container to be replaced without losing config information. A postgres user is also created with a specific UID of 5432 with ownership of this directory, meaning another container can create a postgres user with the same UID and have the correct read permissions on the directory.
As outlined in the comments at the top of the Dockerfile, we can build the image and create the container by running the /bin/true command, which exits quickly leaving a container behind named “data_postgres” with no running processes.
For the application container, the Dockerfile is as follows:
This uses the phusion/baseimage container, which is essentially an Ubuntu 14.04 image with some tweaks to the init process that can monitor and restart processes if they crash. One such service is added for running Postgres, which is defined in an executable bash script as follows:
After building the image and running the container (using the command outlined in the comment at the top of the Dockerfile), we’ll have a container with Postgres running, linked with the data volume created earlier for persisting database data separately, and exposing the Postgres port at 5432 for other containers to access.
The Prosody container is created with the following Dockerfile:
This uses a simple bash script for running the Prosody service:
When creating the image, SSL certificates will be picked up from the certs directory relative to the build path and embedded in the container, as well as the prosody.cfg.lua file which contains the XMPP server settings.
When running the container, a link is made between this container and the Postgres application one, which will set up an entry in this container’s
/etc/hosts file that points to the correct IP for the Postgres container. For example, the Postgres settings for Prosody are set up as follows:
This means the XMPP server can point to a database at host “postgres”, which is the name given to the link, and the correct container IP will be used for writing to the database.
One final note would be around creating new XMPP server users with the prosodyctl command. This means running a command on the Prosody container which doesn’t have SSHD running on it, which can be achieved with nsenter. The easiest way to do this is by running the docker-enter bash script it provides that will inspect running containers by name to retrieve their process ID then enter the namespace of that container:
This will provide a bash terminal inside the Prosody container, which allows the prosodyctl command to be run to set up new users at the XMPP server. This data will be persisted in the data volume created at the start, meaning new Prosody containers can be created at a later time without needing to repeat these steps again for the same users.