Back to all

How to Configure Mosquitto MQTT Broker in Docker

An MQTT broker is an intermediary between MQTT clients that publish messages and subscribers that receive them. All published messages first go to the broker before getting to the subscribers. The broker receives those messages, filters them by topics, and distributes them among subscribers.

Many industries widely use MQTT brokers in IoT (Internet of Things), smart home automation systems, cloud platforms, mobile Internet, Internet of Vehicles, energy, and other areas.

In this article, we will guide you on installing and configuring the Mosquitto MQTT broker Docker container on Windows, Linux, and macOS operating systems and how to test it.

How to install and configure Mosquitto MQTT broker in Docker from scratch

This article will use the open-source messaging broker Eclipse Mosquitto which implements MQTT version 5, 3.1.1, and 3.1. Mosquitto MQTT broker is available for Windows 10 and 11, Linux, and macOS.

For the installation process, we will use the official eclipse-mosquitto image. Alternatively, you can use cedalo/installer, which also allows you to install Mosquitto and other relevant software like Mosquitto Management Center and a data processing solution called Pro Streamsheets.

Installing and configuring the Mosquitto Docker container is practically the same for different operating systems. Prerequisites: you must have Docker installed (Windows users must install Docker Desktop). 

Installation on Windows, Linux, or macOS

In order to install the broker, run the following command:

docker run -it -d --name mos1 -p 1883:1883 -v /etc/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf eclipse-mosquitto:2

The specified commands have several options:

  • -it keeps the container’s virtual terminal open in interactive mode, which allows, to later attach to it and access the container.
  • --name assigns a name to the Docker container. You can use a specified name (in our case, mos1) to identify the container, access it, or perform other docker commands on it.
  • -p 1883:1883 maps a port on your host machine (Docker host) to a container port. If port 1883 on the Docker host is busy, you can use another port, for example -p 18883:1883. Typically, MQTT uses port 1883. You may also add another -p, for example, to map port9001 for Websocket (-p 9001:9001) and/or map 8883 to 8883 for an MQTTS listener. You can map as many ports as you need. Also, note that by default, -p maps all network interfaces of your host to the container (meaning that it maps 0.0.0.0:1883 from your host to 0.0.0.0:1883 of your container). This will directly make the port on your machine open for external connections unless you have a firewall in front. If you need to, you can specify which particular interface of your Docker host to map. For example: -p 127.0.0.1:1883:1883.
  • -v mounts volumes. It links (maps) local files/folders to the container’s files/folders. You can also chain multiple -v flags to create multiple volumes.
  • -d runs the container as a daemon (in the background).

eclipse-mosquitto is the name of the image that will be used as the container’s blueprint. :2 is an image tag, which means that it will download the latest 2.x.x Mosquitto image (2.0.18 is the latest version at the time of editing this article).

When you run the command from above for the first time, it will download the eclipse-mosquitto:2 image from Dockerhub and start it.

Command -v /etc/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf maps a configuration file mosquitto.conf from your Docker host to the container. Basically, your host machine and the docker container will share this file, meaning any changes you perform on this local file will also apply to that same file inside the container.

Path /etc/mosquitto/mosquitto.conf is used as an example. You can change it, but make sure it exists (together with the mosquitto.conf file, which may be left empty for now). The path to the file in the container (i. e. /mosquitto/config/mosquitto.conf) should stay the same as in the example.

If you plan to add more volumes, we recommend you map them to the /mosquitto directory inside the container. For example: -v /etc/mosquitto/dir:/mosquitto/dir or etc/mosquitto/my/long/path/to/something:/mosquitto/something. This will mitigate potential permission issues because the Eclipse Mosquitto container ensures that the mosquitto user, which also runs the broker, owns everything within the /mosquitto directory.

Note:

  • For windows, change the path to windows format like: C:\mosquitto\mosquitto.conf
  • For macOS and Linux, you don’t have to change anything.

If you are on Linux or macOS, we also recommend that you don’t have any users or groups on your system with UID or GID 1883. This id is used for the mosquitto user and group inside the Docker container. There could be potential issues as a result of mixing these ids. You can find more information in the “Troubleshooting Mosquitto MQTT Broker Docker container” section below under “Conflicting UIDs and GIDs inside and outside of the container.” 

After you have started the Mosquitto Docker container with the command above, the broker will run and open its default listener. 

However, by default Mosquitto is configured not to accept any external connections. It is started in local-only mode, so it will only be available inside the container at mqtt://127.0.0.1:1883. You can change this if you add some configuration to the mosquitto.conf file that you mapped. We will explore how this file can be configured in the sections below. The simplest but least secure configuration is just adding allow_anonymous true to the config file.

A small note is that the local-only mode is relevant for Mosquitto version 2.0.0 and higher.

In case you want to attach, i.e., enter the filesystem of the created Mosquitto container, consider the following command:

docker exec -it mos1 sh

By default, you will attach to a container as a root user. However, for the eclipse-mosquitto image, we recommend entering the container under the mosquitto user, which runs the broker. This will minimize the risk of getting permission or ownership issues if you modify any files in the container. The mosquitto user has the UID (user id) 1883, so to enter a container as this user, run the command below:

docker exec -it  -u 1883 mos1 sh

To exit from the container, enter exit.

If you are an advanced Docker user and want to look at the broker’s Dockerfile – refer to the Eclipse Mosquitto Github repository.

Other useful Docker commands

To verify that the container is running, use the command:

docker ps -a

Find your Mosquitto container by its name or id.

If the container is not running, you can find the reasons in the Docker logs:

docker logs <container name or id>

// in our case the container name is mos1

For example:

docker logs mos1

You can stop the Mosquitto MQTT Docker container using the following command:

docker stop <container name or id>

To start the container, use the following command:

docker start <container name or id>

To restart the container, use the following:

docker restart <container name or id>

Run the following command to delete the container:

docker rm <container name or id>

  To delete the downloaded image, run:

docker rmi <image name or id>

  For example:

docker rmi eclipse-mosquitto:2

Mosquitto MQTT Docker authentication settings

You can keep your MQTT broker open – but then any device on your network can reach your Mosquitto server and post messages and subscribe to topics.

To allow external anonymous connections (i.e., without using a dedicated Mosquitto user), you can add the following to the configuration file:

allow_anonymous true
listener 1883 0.0.0.0

The lines above define an anonymous listener that listens on all available network interfaces on port 1883. Provided that you mapped the ports with the -p option when running the docker run command as described earlier, this will make this listener available to your host machine at mqtt://0.0.0.0:1883. This means your broker will also be available to the outside world at port 1883 of your host machine (note that you might have to ensure that your firewall does not block this port if you want it to be externally accessible).

It is possible to omit the IP address (0.0.0.0) in the listener above, but it is recommended to leave it to be more explicit.

Now, restart the container with the broker for the config file changes to take effect. This is possible by issuing the docker restart mos1 command.

It is important to be very careful with anonymous connections. If you want to achieve higher security, do not allow this setting and connect only using authentication. This will require clients to enter the correct username and password in order to write or read messages from the broker.

To set up authentication, first, attach to the container with docker exec -it  -u 1883 mos1 sh and create a password file. Run the following command to create and add a user to this file (note that /mosquitto/passwd_file can be changed to a different path. You can also create a password file inside a mapped volume if you need to):

mosquitto_passwd -c /mosquitto/passwd_file user_name

After that, you will be asked to enter the password for the user you have created and confirm it. For security reasons, the password you enter will not be visible. Once you press enter, your password will be set.

  • If you want to add more users to the password file, use the mosquitto_passwd -b /mosquitto/passwd_file user_name password command. 
  • If you want to remove a user, run: mosquitto_passwd -D /mosquitto/passwd_file user_name

Now, add the following settings to the mosquitto.conf configuration file (and make sure any unsafe anonymous mode settings presented earlier have been deleted):

password_file /mosquitto/passwd_file
allow_anonymous false
listener 1883 0.0.0.0

The parameter allow_anonymous false prevents unauthenticated clients from connecting to the broker. This parameter is set to false by default, but it’s always a good idea to mention it explicitly.

Now exit the container using the exit command and restart it with docker restart mos1. After that, your changes should be applied to the broker.

Alternatively, you may create a password file on your docker host and map it inside the container (-v option of the docker run command). For this, you would have to install mosquitto_passwd utility onto your Docker host.

To install mosquitto_passwd on Linux, you can run either yum install mosquitto-clients or apt install mosquitto-clients, depending on your distribution.

For macOS: run brew install mosquitto. Note that you need to have brew installed first. However, together with the mosquitto_passwd tool, this will also install the Mosquitto broker itself on your host machine.

For Windows: install Mosquitto on Windows from here and find the mosquitto_passwd executable in the installation directory.

After installing mosquitto_passwd, you can use the same commands for creating a password file as shown earlier. mosquitto.conf file changes should also be the same as in the example above.

When mapping a password file from your host machine into the docker container, see the following command for reference:

docker run -it -d --name mos1 -p 1883:1883 -v /etc/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf -v /etc/mosquitto/passwd_file:/mosquitto/config/passwd_file eclipse-mosquitto:2

Again, we recommend mounting all your files and directories into the /mosquitto directory in the container (as done in the example command above) to avoid potential permission issues.

You may also refer to the following documentation page about Mosquitto authentication methods.
Note that for enhanced security, it is also recommended to set up a TLS Mosquitto listener (also called the MQTTS listener), which should be added to the mosquitto.conf file. By convention, MQTTS listeners use port 8883. Be aware that you will also have to add more configuration and set up certificates. The section below demonstrates the basic setup of an MQTTS listener, but for more detailed instructions on obtaining valid certificates, refer to this article.

How to set up persistent storage and logging to a file for Mosquitto Docker Container

Inside the container are three special directories for configuration, permanent storage of data, and logging:

/mosquitto/config
/mosquitto/data
/mosquitto/log

As you have already seen, /mosquitto/config is used for storing configuration like mosquitto.conf. Now, two other directories (/mosquitto/data and /mosquitto/log) are the go-to places for storing persistent data and logs, respectively.

If you want persistent storage and logging for your Mosquitto, add the following lines to the beginning of the mosquitto.conf configuration file in /etc/mosquitto/config that you mounted when creating the container.

persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log

Logs will be stored in /mosquitto/log/mosquitto.log, and all the broker data in the /mosquitto/data/ directory. Note that after applying the directives above, Mosquitto will redirect the logs exclusively to the specified file and will no longer output them to the console. This means you won’t be able to inspect them using the docker logs <container name or id> command. However, if you also want the ability to use this command to view the logs, then add the following to mosquitto.conf right after log_dest file directive:

log_dest stdout

If you want to specify which log types to log, then you can do so by including several log_type directives with the desired log types:

log_type subscribe
log_type unsubscribe
log_type websockets
log_type error
log_type warning
log_type notice
log_type information

Possible values are: debug, error, warning, notice, information, subscribe, unsubscribe, websockets, none, and all. The default values are: error, warning, notice, and information.

Now that you have learned to configure data and logs, you might want to make volumes for them. To do this, when running the docker run command, add two -v flags with <host machine path to data directory>:/mosquitto/data/ and <host machine path to log directory>:/mosquitto/log.

If you have already started the Mosquitto container before, you must stop and delete it with docker stop mos1 and then docker rm mos1. Afterward, run a fresh docker run command with more volumes.

Here is an example which extends the docker run command introduced in the beginning:

docker run -it -d --name mos1 -p 1883:1883 -v /etc/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf -v /var/mosquitto/data:/mosquitto/data -v /var/mosquitto/log:/mosquitto/log eclipse-mosquitto:2

Example Mosquitto configurations (mosquitto.conf files)

Below is a very basic mosquitto.conf file example, which contains recommended settings from the sections above and additional ones.

Feel free to take a look at the default mosquitto.conf for a detailed explanation of every option we discussed and more.

You can also find a complete list of configuration options for the mosquitto.conf file in this documentation.

Basic mosquitto.conf file example:

persistence true
persistence_location /mosquitto/data/
log_type subscribe
log_type unsubscribe
log_type websockets
log_type error
log_type warning
log_type notice
log_type information
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout

password_file /mosquitto/passwd_file
allow_anonymous false

# MQTT Default listener
listener 1883 0.0.0.0

# MQTT over WebSockets
listener 9001 0.0.0.0
protocol websockets

The file above defines an MQTT listener on port 1883 and a WebSocket listener on port 9001. It uses persistent data, writes logs into the console and file, restricts anonymous access, and uses authentication with a password file for both listeners.

Try the following configuration, if you want to define an MQTTS listener with certificates (MQTT over TLS):

persistence true
persistence_location /mosquitto/data/
log_type subscribe
log_type unsubscribe
log_type websockets
log_type error
log_type warning
log_type notice
log_type information
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout

password_file /mosquitto/passwd_file
allow_anonymous false

# MQTT Default listener
listener 1883 0.0.0.0

# MQTT over WebSockets
listener 9001 0.0.0.0
protocol websockets

# MQTT over TLS
listener 8883 0.0.0.0
cafile /path/to/your/ca.crt
certfile /path/to/your/mosquitto.crt
keyfile /path/to/your/mosquitto.key

Below is another mosquitto.conf if you additionally want to use websockets over TLS:

persistence true
persistence_location /mosquitto/data/
log_type subscribe
log_type unsubscribe
log_type websockets
log_type error
log_type warning
log_type notice
log_type information
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout

password_file /mosquitto/passwd_file
allow_anonymous false

# MQTT Default listener
listener 1883 0.0.0.0

# MQTT over WebSockets with TLS
listener 9001 0.0.0.0
protocol websockets
cafile /path/to/your/ca.crt
certfile /path/to/your/mosquitto.crt
keyfile /path/to/your/mosquitto.key

# MQTT over TLS
listener 8883 0.0.0.0
cafile /path/to/your/ca.crt
certfile /path/to/your/mosquitto.crt
keyfile /path/to/your/mosquitto.key

How to use Mosquitto docker-compose set-up

If you want to avoid entering a long docker run command every time you start a container, you can use a docker-compose file. It allows you to define the docker containers you need to run as services and uses a simple docker-compose up command to start everything up. This is especially useful for automation.

You must first install docker-compose (for Windows it is typically installed with Docker Desktop by default). Then create a docker-compose.yml file with the following content:

version: '3.8'

services:
    mosquitto:
        image: eclipse-mosquitto:2
        ports:
            - 1883:1883
            - 8883:8883
            - 9001:9001
        volumes:
            - ./mosquitto/config:/mosquitto/config
            - ./mosquitto/data:/mosquitto/data
            - ./mosquitto/log:/mosquitto/log
        networks:
            - mosquitto
networks:
    mosquitto:
        name: mosquitto
        driver: bridge

Save your mosquitto.conf file in your machine’s mosquitto/config directory or choose a different path (and modify the compose file accordingly).

Remember that paths before the : in the volumes section of the file are the paths of your host machine. You can adjust them as needed.

Then run the following command from the directory with docker-compose.yml file to start Mosquitto in the detached mode (in the background):

docker-compose up -d

The name of the container will be the project name (which by default is the the name of the directory where the docker-compose file is located), followed by the name of the service (i.e., mosquitto) and the instance number (relevant if you have scaled a service, the instance number equals “1” by default). For example: mosquitto_dir_mosquitto_1 (if docker-compose.yml is located in /etc/mosquitto_dir/).

If you want to change the project name (i.e., the first part of the container name), then specify a COMPOSE_PROJECT_NAME environment variable or use a -p command line argument (e.g., docker-compose -p <your project name here> up -d).

Note that if you are using the -p flag, you will also have to use it when stopping docker compose (i.e., docker compose -p <your project name here> down) .

If you want to set an entirely custom name for the container, add a property container_name (e.g., container_name: mos1) on the same level as image and ports properties right under mosquitto service entry.

Note: if you get an error saying “Version in ./docker-compose.yml is unsupported.” or similar, consider lowering the version property in the docker-compose file from 3.8 to 3.7 or lower.

To shut down the container and delete it, execute the following command from the directory with the docker-compse.yml file:

docker-compose down

You can add more services (containers) to your compose file. And also add or remove volumes.

How to test the Mosquitto docker configuration

To test the correct operation of the broker, you can use any MQTT client. In our example, we will use the Paho Python Client, which provides a client class with all the necessary functionality for publishing messages and subscribing to topics. We will also briefly show examples of using  mosquitto_pub and mosquitto_sub command line utilities.

Alternatively, you can also use a UI tool called MQTT Explorer. However, we will not describe this tool here.

Let’s start by testing with Paho Client first and then move on to `mosquitto_pub` and `mosquiito_sub`. This way you can choose which tool to use for yourself.

Testing with Paho Client

First, have Python and Pip installed. Then, install the Paho Python Client using the following command:

pip install paho-mqtt

Publish

Import the Paho Python Client and “time” libraries.

import paho.mqtt.client as mqtt 
import time 

Then, add an on_connect callback to check whether we are connected to the broker or not.

def on_connect(client, userdata, flags, return_code):
    if return_code == 0:
        print("connected")
    else:
        print("could not connect, return code:", return_code)

Then, you need to actually initiate a connection with the broker by specifying its hostname and port and creating a client object with a unique identifier (in our example, it is Client1).

This example can be used with the “anonymous connections” setting, both enabled and disabled. If you are using the username-password approach and have anonymous connections disabled, uncomment and edit the line with client.username_pw_set in the code snippets below.

For proper and faster communication with the broker, start the Paho Client’s network loop by calling loop_start.

broker_hostname = "localhost"
port = 1883 

client = mqtt.Client("Client1")
# client.username_pw_set(username="user_name", password="password") # uncomment if you use password auth
client.on_connect = on_connect

client.connect(broker_hostname, port)
client.loop_start()

To publish messages, we will create a while loop. In this loop, we will publish a new message every second for 10 seconds to the topic defined by the topic variable. Then, check whether the message was published successfully and display the corresponding message on the screen. To disconnect the client and clean up the thread where the Paho Client’s network loop lives, add a try-finally block to call client.disconnect and client.loop_stop at the end.

topic = "Test"
msg_count = 0

try:
    while msg_count < 10:
        time.sleep(1)
        msg_count += 1
        result = client.publish(topic, msg_count)
        status = result[0]
        if status == 0:
            print("Message "+ str(msg_count) + " is published to topic " + topic)
        else:
            print("Failed to send message to topic " + topic)
            if not client.is_connected():
                print("Client not connected, exiting...")
                break
finally:
    client.disconnect()
    client.loop_stop()

The complete code example for publishing messages is as follows:

import paho.mqtt.client as mqtt 
import time

broker_hostname = "localhost"
port = 1883 

def on_connect(client, userdata, flags, return_code):
    if return_code == 0:
        print("connected")
    else:
        print("could not connect, return code:", return_code)

client = mqtt.Client("Client1")
# client.username_pw_set(username="user_name", password="password") # uncomment if you use password auth
client.on_connect = on_connect

client.connect(broker_hostname, port)
client.loop_start()

topic = "Test"
msg_count = 0

try:
    while msg_count < 10:
        time.sleep(1)
        msg_count += 1
        result = client.publish(topic, msg_count)
        status = result[0]
        if status == 0:
            print("Message "+ str(msg_count) + " is published to topic " + topic)
        else:
            print("Failed to send message to topic " + topic)
            if not client.is_connected():
                print("Client not connected, exiting...")
                break
finally:
    client.disconnect()
    client.loop_stop()

Now we can run the script with python <path to your python file> or python3 <path to your python file>. The output in the console should look like this:

Message 1 is published to topic Test
Message 2 is published to topic Test
Message 3 is published to topic Test
Message 4 is published to topic Test
Message 5 is published to topic Test

Subscribe

Now, let’s create a subscriber. As in the previous example, we should import the Paho Python Client and the auxiliary standard library time.

import paho.mqtt.client as mqtt
import time

Add on_connect callback to be notified when the connection to the broker is established. To subscribe to a topic, add the client.subscribe(topic_name) call to that callback to ensure that we subscribe only when the connection is established. If the connection fails, set a custom property failed_connect on the client object to communicate this information to the main thread and exit the program earlier.

def on_connect(client, userdata, flags, return_code):
    if return_code == 0:
        print("connected")
        client.subscribe("Test")
    else:
        print("could not connect, return code:", return_code)
        client.failed_connect = True

Whenever the client receives a message from the broker, it invokes the on_message callback. So, to be able to view these messages, we need to define this  callback function as shown below:

def on_message(client, userdata, message):
    print("Received message: ", str(message.payload.decode("utf-8")))

Then, like the previous example, create a new client, connect to a broker, and start a network loop with loop_start.

broker_hostname ="localhost"
port = 1883 

client = mqtt.Client("Client2")
client.connect(broker_hostname)
# client.username_pw_set(username="user_name", password="password") # uncomment if you use password auth
client.on_connect = on_connect
client.on_message = on_message
client.failed_connect = False

client.loop_start()

Adding a timer will keep our subscribing client alive for 15 seconds in a try-finally block that calls client.disconnect and client.loop_stop in the end to do some cleanup. The “finally” clause will also be called if you decide to terminate the client midway with the “Ctrl + C” shortcut  (or “Command +” for MacOS), which will generate an exception in Python.Additionally, if the connection to the broker has failed and therefore client.failed_connect is true, the timer will not be executed, and we will immediately leave the program.

# this try-finally block ensures that whenever we terminate the program earlier by hitting ctrl+c, it still gracefully exits
try:
    i = 0
    while i < 15 and client.failed_connect == False:
        time.sleep(1)
        i = i + 1
    if client.failed_connect == True:
        print('Connection failed, exiting...')

finally:
    client.disconnect()
    client.loop_stop()

Below is the complete code for creating a client that subscribes to messages on the “Test” topic.

import paho.mqtt.client as mqtt
import time

def on_connect(client, userdata, flags, return_code):
    if return_code == 0:
        print("connected")
        client.subscribe("Test")
    else:
        print("could not connect, return code:", return_code)
        client.failed_connect = True


def on_message(client, userdata, message):
    print("Received message: ", str(message.payload.decode("utf-8")))


broker_hostname ="localhost"
port = 1883 

client = mqtt.Client("Client2")
# client.username_pw_set(username="user_name", password="password") # uncomment if you use password auth
client.on_connect = on_connect
client.on_message = on_message
client.failed_connect = False

client.connect(broker_hostname, port) 
client.loop_start()

# this try-finally block ensures that whenever we terminate the program earlier by hitting ctrl+c, it still gracefully exits
try:
    i = 0
    while i < 15 and client.failed_connect == False:
        time.sleep(1)
        i = i + 1
    if client.failed_connect == True:
        print('Connection failed, exiting...')

finally:
    client.disconnect()
    client.loop_stop()

If you have a specific topic that you want to subscribe to and test, then edit the client.subscribe("Test") line from above. Otherwise, you can leave it unchanged.

To test the whole setup, first run the subscribe script and, in another terminal, publish the script from the previous section. You should then see the following output in your first terminal window:

Received message: 1
Received message: 2
Received message: 3
Received message: 4
Received message: 5

Testing with mosquitto_pub mosquitto_sub

If you are using Linux, you can install mosquitto_pub and mosquitto_sub tools by installing the mosquitto-clients package. For Windows, download the executables for these commands together with Mosquitto for Windows from here. mosquitto_pub and mosquitto_sub will be stored in the installation directory. For macOS – install the mosquitto package using brew install mosquitto.

Publish

Run one of the commands below by replacing <username> and <password> with credentials you created for the broker user earlier, or omit -u and -P options altogether if you are using anonymous connections.

If you are on Linux or macOS:

for i in {1..10}; do (mosquitto_pub -i mosq_pub1 -t "Test" -m "Message with ID: $i" -u <username> -P <password> -d & sleep 1); done

If you are on Windows and are using PowerShell, run the following:

1..10 | ForEach-Object { mosquitto_pub -i mosq_pub1 -t "Test" -m "Message with ID: $_" -u <username> -P <password> -d; Start-Sleep -Seconds 1 }

And for Windows Command Prompt (cmd), use the command below:

for /L %i in (1,1,10) do (mosquitto_pub -i mosq_pub1 -t "Test" -m "Message with ID: %i" -u <username> -P <password> -d & timeout /t 1)

Note that to run mosquitto_pub and mosquitto_sub commands on Windows, you will need to navigate inside the installation folder of your Mosquitto broker (unless you add this folder to the PATH environment variable to make the utilities from this folder globally available). You may also need to replace mosquitto_pub and mosquitto_sub in commands from above with .\mosquitto_pub and .\mosquitto_sub respectively.

The output of the commands above will be similar to what we had with the publish Paho Python script.

Subscribe

Run the following command (regardless of your OS) in a new terminal, replacing <username> and <password> accordingly or omitting them:

mosquitto_sub -i mosq_sub1 -t "Test" -u <username> -P <password> -d

Now, for the complete set-up, run the mosquitto_pub again in a separate terminal and return to the terminal with mosquitto_sub. If you start seeing the messages published by mosquitto_pub, then everything is working as expected.

Advantages of Pro edition for Eclipse Mosquitto broker

In addition to the open-source version, the Pro Edition for Eclipse Mosquitto is also available and offers a number of advantages comparable to that of the open-source version.:

  • Cloud hosting is available.
  • Reliable support, as well as SLA and professional services are available for product customization.
  • High availability.
  • Offers a REST API that allows Pro Mosquitto to integrate features into the software infrastructure of the customers’ systems.
  • Support for advanced user management and permission control, use of client certificates and custom certificate authorities, application tokens, etc., to ensure data security.
  • Deep inspection features provides a list of connected clients on a node, and detailed information about each MQTT client (status, protocol information, IP address, TLS encryption information, last-will messages, topics you subscribe to, and more).
  • LMDB (Lightning Memory-Mapped Database) persistence feature. 

Sign up for a free 14-day trial to test the Pro Edition for Eclipse Mosquitto broker and evaluate its benefits.

Troubleshooting Mosquitto MQTT Broker Docker container

During the installation and configuration of the broker, errors may occur. Let’s address some of the most common ones.

Address not available

After installing the Mosquitto MQTT docker image and starting the container, the “Address not available” error may occur.

Possible solutions:

  1. If you want to allow clients to connect to the broker without authorization, add the following settings to the configuration file:
allow_anonymous true
listener 1883

2. If you want to prevent unauthorized clients from connecting to the broker, then create a file that will contain the username and password and add the following lines to the configuration file:

password_file /mosquitto/passwd_file
allow_anonymous false

After that, restart the Docker container.

Address already in use

This error may mean that the specified port is already occupied or that Mosquitto is already running.

Possible solutions:

  1. Try uninstalling all previously running versions of Mosquitto.
  2. Find which application is occupying the port and try to terminate or kill it (for example, using netstat and kill or taskkill tools)
  3. Use a different port for the broker.

The client does not receive the expected messages

Possible reasons:

  1. Unstarted network loop loop_start() in case of Paho client.
  2. The callback function was not created or assigned to the client.
  3. The client is not subscribed to the correct topics or an error occurred while creating the subscription.
  4. Broker’s access restriction policies apply (you may need to check your Mosquitto configuration).

Volumes don’t work for Windows

On Windows users can experience problems with docker volumes where the volumes might not mount at all.

Possible solutions:

  1. Use cmd or PowerShell, and make sure that the paths are correct and are defined in the Windows format.
  2. Make sure that you have shared drives enabled in your Docker Desktop settings (however, this setting might not be available in some installations).
  3. Try installing docker directly onto the WSL without Docker Desktop and use it from the WSL (though this approach is a bit more complicated).

Permission issues

The directories and files you map into your container (with -v option) must be accessible by the mosquitto user and the group that Mosquitto is running as. You can usually identify this issue by the “Permission denied” message in the logs.

Usually, this problem should not arise if all your volumes are mounted into /mosquitto directory inside the Docker container. This is because before starting the broker, the Mosquitto Docker container sets the ownership of all the files and directories inside /mosquitto to the mosquitto user and group. However, if you are not mapping into the /mosquitto directory (which is not recommendable), the possible solutions are:

  1. Manually ensure that the mosquitto user or group owns all of your mapped files and directories. Note that the default UID and GID for this user/group is 1883. (for example, using chown 1883:1883 /path/to/file/or/dir).
  2. Alternatively, you would have to expand the o (others) permission bit of your mapped files and directories.

The described approaches work for Unix systems like Linux or macOS. For Windows, we strongly advise sticking to mappings into the /mosquitto directory on the container side.

Conflicting UIDs and GIDs inside and outside of the container

This problem is relevant for Unix (Linux, macOS) systems.

As mentioned, the Mosquitto broker within the container runs under the mosquitto user with UID 1883. If you have a user on your host machine with the same UID this might lead to potential problems.

If you map any directories containing files owned by the host machine user with UID 1883, then from the container’s perspective, the mosquitto user will own those files and be accessible to Mosquitto. This might not pose a direct security vulnerability but might lead to confusion in some instances.

A more problematic situation could arise if the broker generates any files like log files, persistent data files, potentially a password file, etc. In this case, UID 1883 will own those files. If you have a user on your system with the same UID, then this user will be able to access those files even if you didn’t intend it. The same is true for a group with GID 1883.

For the reason above, we recommend avoiding having users and groups with UID or GID equal to 1883 when running the Mosquitto docker image.

Possible solutions:

1. You may create a custom Dockerfile which will extend the original eclipse-mosquitto:2 image and use usermod and groupmod commands to modify the UID and GID of the mosquitto user such that they are different from the ones from your host machine.

In this case, you would have to create a Dockerfile similar to the one below:

FROM eclipse-mosquitto:2
RUN apk add --no-cache shadow # install usermod and groupmod utilities
RUN usermod -u 9999 mosquitto # change GID 9999 to whatever UID you don't have on your system 
RUN groupmod -g 9999 mosquitto # change GID 9999 to whatever GID you don't have on your system

Then, you can build your custom image with the following:

docker build -t new_image_name

And use it instead of eclipse-mosquitto:2.

2. You may prefer to change the UID and GID on your host machine rather than in the container. Be careful in this case, as there might be a lot of potential pitfalls when changing the UIDs and GIDs of existing users or groups.

Below is the example command to achieve this – but use extreme caution. Only when you have a thorough understanding of what you are doing should you use the command:

sudo usermod -u newUID username
sudo groupmod -g newGID groupname

After that, you should update the file ownership for all the files owned by the old UID and GID to the new ones:

sudo find / -user oldUID -exec chown -h newUID {} \;
sudo find / -group oldGID -exec chgrp -h newGID {} \;

Summary

In this article, we explained how to install and configure the open-source version of the Eclipse Mosquitto broker on Windows 10 and 11, Linux, and macOS operating systems using the Docker containerization tool. We also learned how to subscribe to topics and publish messages using the Mosquitto MQTT broker. 

Let’s recap the most important points:

  • The installation process of the Mosquitto broker is practically the same for all the operating systems.
  • To install the Mosquitto broker, we need to use the “eclipse-mosquitto” image and run it either with a ‘docker run’ command:
docker run -it -d --name mos1 -p 1883:1883 -v /etc/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf eclipse-mosquitto:2

or use the docker-compose up -d and the provided docker-compose.yml file.

  • To configure Mosquitto to your needs, mount a volume with a mosquitto.conf configuration file, and other volumes for logs, persistent data, etc.
  • You can test whether your Mosquitto installation and configuration worked using Paho Python Client or other means like MQTT Explorer, mosquitto_pub, and mosquitto_sub commands.

If you plan to use the open-source version of Mosquitto for commercial purposes, you may have concerns about the possible issues arising in production. That is why we offer open-source Mosquitto support to ensure the stability and security of your system.

Click to rate this post!
[Total: 9 Average: 5]
About the author
Serhii Orlivskyi

Serhii Orlivskyi

Full-stack software developer at Cedalo

Serhii Orlivskyi is a full-stack software developer at Cedalo GmbH. He previously worked in the Telekom industry and software startups, gaining experience in various areas such as web technologies, services, relational databases, billing systems, and eventually IoT.

While searching for new areas to explore, Serhii came across Cedalo and started as a Mosquitto Management Center developer. Over time, Serhii delved deeper into the MQTT protocol and the intricacies of managing IoT ecosystems.

Recognizing the immense potential of MQTT and IoT, he continues to expand his knowledge in this rapidly growing industry and contributes by writing and editing technical articles for Cedalo's blog.

Newsletters icon

Subscribe for monthly updates