Running The Mosquitto MQTT Broker In Docker – Beginners Guide

docker-mos-iconDocker is a container technology used for quickly deploying applications without having to install them.

The applications come pre-installed as a docker images which are used to create docker containers which can run on window,Linux and Mac OS under Docker.

Mosquitto ships docker containers for various mosquitto versions and the list along with install instructions are available here

docker-images

 

 

 

 

Before you can run Mosquitto under Docker you will need to install Docker and that is covered here.

Note: I am not a Docker expert and this tutorial is based on my experience of running and configuring a test mosquitto broker.

Why Use Docker?

Installing mosquitto is quite straightforward so why bother with Docker?

For me the main advantage is the ease of upgrade and the isolation from other applications on the host.

Ease of Upgrade

On a normal install upgrading overwrites the existing version which can be a problem if you experience problems with the upgrade or the upgrade version doesn’t work as expected.

Application Isolation

Most applications have library dependencies and so it you install/upgrade an application on your host it could change a library than Mosquitto depends on causing unexplained problems.

Docker Images vs Containers

A Docker image is the actual code to run the application which serves as a template.

A container is then created from an image. Multiple containers can be created from a single image each with its own configuration. See images vs containers

The Docker Container and Your Host Machine

One difficulty I had when I ran my first docker application is understanding the relationship between the docker container and the host machine.

The schematic below will I hope help you to conceptualise it.

Docker-Container-Schematic

Clients Interact with mosquitto using a port (1883) or ports.

So how do clients access the mosquitto broker running inside the container?

The answer is that the container ports need to be mapped to the host port.

So if mosquitto in the container uses port 1883 then this needs to be mapped to a port on the host machine e.g.1883.

If mosquitto uses several ports then all these ports need to be mapped to be usable.

You should note that the docker port and the host port can be different but they are usually the same to avoid confusion.

Important ! -The mosquitto broker in the container uses the same IP address and name as the host machine.

This especially important when using certificates or opening ports on a firewall.

Configuring Mosquitto In Docker

When you install mosquitto on your system you need to configure it using the mosquitto.conf file located in the /etc/mosquitto folder.

In addition you may also need to provide a password and ACL (access control list) file,certificate files, log folders etc.

Changing or adding files to the container itself is not normally done.

Instead the container provides directories that can be mapped to folders on the host machine.

The Mosquitto image creates a container that provides 3 folders as described in the documentation

  • Configuration /mosquitto/config/mosquitto.conf
  • persist data to /mosquitto/data
  • log to /mosquitto/log/mosquitto.log

To access data in these folders and make changes you can map them to folders outside the container.

This is done with the -v switch when we run the container.

Note: Mapping is optional and dependent on your requirements

Choosing a Location for the Mapped files/folders

If you are mapping folders then you should try to put them in a recognisable location.

On my system I have a folder called containers (previously used mos-docker) and in this folder I create a folder  for each container as shown below:

docker-container-folder

The mosquitto folder looks like this:

docker-mosquitto-folder

The mapping is done as follows:

  • -v /home/steve/containers/mosquitto/ssl.conf:/mosquitto/config/mosquitto.conf
  • -v ./containers/mosquitto/passwords.txt:/mosquitto/passwords.txt
  • -v ./containers/mosquitto/data:/mosquitto/data
  • -v ./containers/mosquitto/log:/mosquitto/log
  • -v ./containers/mosquitto/certs:/mosquitto/certs

Notice I’ve used relative links to shorten the command and my conf file is actually called ssl.conf as it is my conf file when using SSL.

The name of the configuration file on the host isn’t important but it should always be mosqutto.conf in the container.

Container Names and Ids

Every container is given a unique container Id but you can give it an optional name.

Names are much easier to use, and so you should always use them.

The names you assign must be unique.

Getting Docker Images

You will need to know the image name and then you can use the docker pull command. The format is

docker  pull image_name

example

docker pull eclipse-mosquitto

You can also download the image when you create the container using the run command.

The run command checks to see if the image exists locally and if not it downloads it onto your local system.

Creating the Container and Running it

The image serves as a template to start the application,in this case Mosquitto, you need to run it in a container.

This you do using the docker run command or the docker create command.

docker create will create the container but not run it, whereas docker run creates and runs it.

There are various switches that can be used as options, the common ones are

–name    //assign a name to the container
-p           //map a port
-v           //map a volume to the local file system
-d           //run in the background as a daemon
-it           //run with a display console

You only need to create the container once using the run/create command.

Once you have done that you start and stop the container using the start and stop commands. So

  • docker run ……options
  • docker stop (container name or id)
  • docker start (container name or id)

If you make changes to the configuration file then you will need to stop and restart the container.

When using a name with the container that name is associated with the container image until you remove it using the rm command.

If you need to restart the container with a different mapping for example, then you will need to remove the container or use a different container name.

To remove a container use the docker rm container name command. e.g for a container called mos-basic use:

docker rm mos-basic

Docker Run Examples:

Example 1: Run and map port and volumes:

We start by using the run command with :
-it to attach console
–name to give it a name (mos2)
-p map the internal to external ports to use
-V link the local folders to the container folders

The mosquitto image is called eclipse-mosquitto

The local folders are under the mos-docker/mosquitto folder in my home folder. (Note: I now use a different location of containers/mosquitto).

The Port is 1883
Volumes : Map config folder, data folder and log folder.
The command is:

docker run -it --name mos2 -p 1883:1883  -v /home/steve/mos-docker/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf -v ~/mos-docker/mosquitto/log:/mosquitto/log -v ~/mos-docker/mosquitto/data:/mosquitto/data  eclipse-mosquitto

and this is shown in the screen shot below:
docker-run

 

 

 

We then stop the broker using control+C and now we can start and stop the broker using the name, and notice that there is no console until we use the attach command.

After using the attach command I publish a message from an external client and it shows on the console.

docker-attach

Finally I use the rm command to remove the container image so I can now reuse the name.

docker-rm

Example 2: Run and map two ports(1884,8883) and volumes:

Command:

docker run -it --name mos2 -p 1883:1883 -p 8883:8883  -v /home/steve/mos-docker/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf -v ~/mos-docker/mosquitto/log:/mosquitto/log -v ~/mos-docker/mosquitto/data:/mosquitto/data  eclipse-mosquitto

Configuration changes

In both examples 1 and 2 we have mapped volumes and to change the broker configuration we edit the local mosquitto.conf  configuration file.

The changes will automatically be copied over into the container and then we will  need to stop and restart the container for the changes to take affect.

Example 3: Run and map port 1883 but no mapped volumes

Command:

docker run -it --name mos-basic -p 1883:1883  eclipse-mosquitto

In this example because we haven’t mapped any volumes we need to go into the container to edit the mosquitto.conf file. This we can do using this command:

docker exec -it mos-basic sh

I prefer to create a local file and copy it into the container as I find this easier.

docker cp ~/containers/mosquitto/mosquitto.conf mos-basic:/mosquitto/mosquitto.conf

Note: Because the default mosquitto.conf file doesn’t contain any settings you will only be able to access this using a client on the localhost as shown in the screen shot below:

mos-basic

Mosquitto.conf File

The screen shot below shows my local folders:

docker-mosquitto-folder

Note: because I was testing configurations my config file is called ssl.conf and not mosquitto.conf

Below is a simple configuration example

docker-mosquitto.conf

Notice the file locations in the configuration file are locations in the container, and are not referenced to my home folder even though that is where they will also go if I map the folders.

It is important to note that the configuration file puts the persistence data in the /mosquitto/data folder but it  gets copied to the ~/containers/mosquitto/data folder.

In my folder layout you can also see a certs folder there for certificates and this is where I place the certificates and the entries in the mosquitto.conf file would look like this:

docker-mosquitto-certs

 

To create the folders in the container I entered the container and manually created them using the mkdir command.

Once I had created them I manually copied them using the docker cp command.

If you are using passwords then you would also do it this way.

Example-Changing the Run Command

If you have as an example created a container using the command.

docker run --name mos-basic -p 1883:1883 eclipse-mosquitto

Now the container has been running for a while and you decide to use port 1884 in addition to 1883 so what do you do?

You cannot start the container using

docker run --name mos-basic -p 1883:1883 -p1884:1884 eclipse-mosquitto

as docker will complain that the name is in use.

However you could use a new name

docker run --name mos-basic2 -p 1883:1883 -p1884:1884 eclipse-mosquitto

However now you have a brand new container and you will need to copy the mosquitto.conf file over to the new container unless you have been using folder mapping.

Because using a different name means starting from scratch, then you would instead then just remove the old container and recreate it using the new run command.

Viewing Log files

If you have mapped the log folder then these logs are available on the local host in the chosen folder.

However you can also go into the container and use the command

tail -n20 /mosquitto/log/mosquitto.log

or

tail -n20 -f /mosquitto/log/mosquitto.log

view-logs-docker-mosquitto

In addition, if you have enabled logging to stdout in the config file:

log_dest stdout

then you can use the docker logs container name command.

docker-mosquitto-logs

 

Common Questions and Answers

Q- Can I run mosquitto in docker without mapping Volumes?

A- Yes -You will need to manually copy over the config file and restart.

Q- I’m using SSL on port 8883 and MQTT on port 1883 how do I do this.

A- Use: docker run -it –name mos2 -p 1883:1883 -p 8853:8883

Q- I have tried to view mosquitto logs using the docker logs containName command but can’t see them.

A- You haven’t enable logging to stdout in the mosquitto.conf file

Q- Mosquitto is running in a docker container on port 1883. Can I also run mosquitto on the host using the same port 1883.

A- No as the port is already in use.

What I do at the moment.

I don’t map the mosquitto.conf file using the -v option. Instead I just copy it over using the docker cp command.

  • I don’t map the log files
  • I map the persistent data
  • I log to stdout.

Videos

 

Related articles and resources

 

Please rate? And use Comments to let me know more

5 comments

  1. Hi Steve, Hope you’re doing well. I worked with docker mosquitto and tested bridge between 2 brokers and it worked but once I wanted use tls between bridges, it didn’t work. and that was interesting because when I used the exact config in tow normal mosquitto on ubuntu it works well without any problem. could you test it?

  2. Will you be using docker for most of your installations in the future?

    When would you use and and when would you not use it?

    Could you see any performance hit from using docker?

    Thanks for such an interesting article!

    1. Good question but as I don’t use Mosquitto in any real world application then I will be working with both. My preference would be a normal setup but Docker implementations seem to be common.
      Rgds
      Steve

Leave a Reply

Your email address will not be published. Required fields are marked *