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 reaching 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 tutorial, I will guide you through installing and configuring the Mosquitto™ MQTT broker Docker container on Windows, Linux, and macOS operating systems and show you 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 protocol 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, I 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.
If you want to achieve more with enhanced MQTT broker functionality like advanced broker and client monitoring, role-based user management, rich integrations, and other features – sign up for a trial version of Pro Mosquitto now.
Installing and configuring the Mosquitto Docker container is a uniform process across different operating systems. This ensures a consistent experience regardless of your platform. Prerequisites: you must have Docker installed (Windows users must install Docker Desktop).
Installation on Windows, Linux, or macOS
In order to install the MQTT 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 it to attach to and access the container later.--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.-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. For example, you may also add another-p
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 open the port on your machine for external connections unless you have a firewall. 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, meaning it will download the latest 2.x.x Mosquitto image (2.0.18 is the latest version when 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, 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. Mixing these IDs could cause issues. 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 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.
If you want to deploy Mosquitto in another container management system, you can check out this article explaining how to configure Mosquitto MQTT broker in Kubernetes.
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, 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. If 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 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.
- 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, create a password file on your docker host and map it inside the container (-v
option of the docker run command). You would have to install the mosquitto_passwd
utility onto your Docker host for this.
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 from here and find the mosquitto_passwd
executable in the installation directory.
After installing mosquitto_passwd
, you can use the same commands to create a password file as shown earlier. mosquitto.conf file changes should 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, I 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 docs 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 must also 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 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, 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
For additional information on logging in the Mosquitto MQTT broker, check out this article.
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 I have discussed so far 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 MQTT Broker Docker-Compose setup
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 command 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 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 must also 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
You can use any MQTT client to test the broker’s correct operation. In this example, I will use the Paho Python Client, which provides a client class with all the necessary functionality for publishing messages and subscribing to topics. I 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.
LLet’s begin our testing journey with the Paho Client, and then I’ll explore ‘mosquitto_pub’ and ‘mosquiito_sub’. This approach allows you to exercise your autonomy and choose the tool that best suits your needs.
If you want to learn more about how to use the Paho MQTT client in Python, check out this article here.
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 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 use 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 you 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, 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 clients 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, let’s 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 subscribing 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 (check out this PDF document to see a complete comparison between the open-source version of Mosquitto and the Pro Edition for Eclipse Mosquitto):
- Offers a set of powerful MQTT REST APIs that allows Pro Mosquitto to integrate features into the software infrastructure of the customers’ systems, as well as help Mosquitto Management Center manage the broker.
- 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.
- Persistent Queueing allows the MQTT broker to expand its storage capacity, while optimizing resource usage and facilitating scalability for future growth and higher message volumes.
- Numerous MQTT integrations, allowing the broker to establish seamless connections with Kafka, MongoDB, Google Pub/Sub, Google AlloyDB, MySQL, PostgreSQL, TimescaleDB, InfluxDB, Prometheus and others to enable advanced analysis, ensure optimal service performance, reliability, capacity planning, and rapid anomaly detection and response.
- Deployoment of Pro Mosquitto in Kubernetes, Docker, OpenShift, RPM, and more.
Sign up for a free cloud or on-premises trial to test the Pro Edition for Eclipse Mosquitto broker and evaluate its benefits.
Troubleshooting Mosquitto MQTT Broker Docker container
Errors may occur during the broker’s installation and configuration. 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:
- 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:
- Try uninstalling all previously running versions of Mosquitto.
- Find which application is occupying the port and try to terminate or kill it (for example, using netstat and kill or taskkill tools)
- Use a different port for the broker.
The client does not receive the expected messages
Possible reasons:
- Unstarted network loop loop_start() in case of Paho client.
- The callback function was not created or assigned to the client.
- The client is not subscribed to the correct topics, or an error occurred while creating the subscription.
- 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:
- Use cmd or PowerShell, and ensure that the paths are correct and are defined in the Windows format.
- Make sure that you have shared drives enabled in your Docker Desktop settings (however, this setting might not be available in some installations).
- 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. These are the entities that require access to the mapped files and directories. 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:
- 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
). - 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. This underscores the importance of avoiding unintended access to files.
For the reason above, I 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. It’s crucial to note that you may prefer to change the UID and GID on your host machine rather than in the container. However, exercising caution is paramount in this case, as there might be a lot of potential pitfalls when altering 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, I 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, 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 the Cedalo team also offers open-source Mosquitto support to ensure the stability and security of your system.
About the author
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.