dhi.io/eclipse-mosquitto
Eclipse Mosquitto is an open-source MQTT message broker implementing MQTT 5.0, 3.1.1 and 3.1. This Docker Hardened Image provides the Mosquitto broker and client utilities in a minimal, security-focused container with configuration at /mosquitto/config/mosquitto.conf.
All examples in this guide use the public image. If you've mirrored the repository for your own use (for example, to your Docker Hub namespace), update your commands to reference the mirrored image instead of the public one.
For example:
dhi.io/<repository>:<tag><your-namespace>/dhi-<repository>:<tag>For the examples, you must first use docker login dhi.io to authenticate to the registry to pull the images.
This Docker Hardened mosquitto image includes:
The image runs the Mosquitto broker with the default configuration file at /mosquitto/config/mosquitto.conf. Adjust the configuration by mounting your own mosquitto.conf and related files.
$ docker run -d --name mosquitto -p 1883:1883 -p 9001:9001 \
-v /path/to/conf:/mosquitto/config \
-v /path/to/data:/mosquitto/data \
-v /path/to/log:/mosquitto/log \
dhi.io/eclipse-mosquitto:<tag>
version: '3.8'
services:
mosquitto:
image: dhi.io/eclipse-mosquitto:<tag>
container_name: dhi-eclipse-mosquitto
restart: unless-stopped
ports:
- "1883:1883"
- "9001:9001"
volumes:
- ./config:/mosquitto/config:ro
- ./data:/mosquitto/data
- ./log:/mosquitto/log
environment:
- TZ=UTC
Mount a custom config directory (./config) that contains mosquitto.conf and any password/certs you need. Use :ro for config to prevent accidental modification by the container.
Run a transient broker for testing clients locally. Use a mounted config with anonymous access enabled or create a simple password file.
# start a local broker with default config
docker run -d --name local-mosq -p 1883:1883 \
-v $(pwd)/config:/mosquitto/config \
dhi.io/eclipse-mosquitto:<tag>
# publish a test message (override entrypoint to run mosquitto_pub)
docker run --rm --entrypoint /usr/bin/mosquitto_pub \
dhi.io/eclipse-mosquitto:<tag> -h host.docker.internal -t test/topic -m "hello"
Example mosquitto.conf snippets (place into ./config/mosquitto.conf):
# listener for plaintext MQTT
listener 1883
allow_anonymous false
password_file /mosquitto/config/passwordfile
# TLS listener
listener 8883
cafile /mosquitto/config/certs/ca.crt
certfile /mosquitto/config/certs/server.crt
keyfile /mosquitto/config/certs/server.key
# Websockets listener
listener 9001
protocol websockets
The DHI Mosquitto image differs from the upstream image in several ways:
The DHI image runs the mosquitto broker directly as the entrypoint (/usr/sbin/mosquitto), while the upstream image
uses a shell script entrypoint (/docker-entrypoint.sh) that allows running utilities directly. This means:
When migrating from upstream, update commands that run mosquitto utilities. The upstream image allows running utilities
like mosquitto_passwd directly, but the DHI image requires overriding the entrypoint. See
Running mosquitto utilities for detailed examples of all utilities.
Mosquitto's official image relies primarily on configuration files rather than environment variables. The DHI mosquitto image follows the same pattern: configure the broker via /mosquitto/config/mosquitto.conf and supporting files (password file, TLS certs, etc.). Common container environment variables you may set:
| Variable | Description | Default | Required |
|---|---|---|---|
| TZ | Timezone for logs and system utilities | UTC | No |
Use mosquitto_passwd to create a password file. The DHI image runs the mosquitto broker directly as the entrypoint, so you must override the entrypoint to run utilities like mosquitto_passwd:
# create a password file with a user 'testuser'
docker run --rm -v $(pwd)/config:/mosquitto/config \
--entrypoint /usr/bin/mosquitto_passwd \
dhi.io/eclipse-mosquitto:<tag> -b /mosquitto/config/passwordfile testuser 's3cret'
After creating the passwordfile, restart the broker so it picks up the new file.
The DHI image runs the mosquitto broker directly as the entrypoint (/usr/sbin/mosquitto), unlike the upstream image
which uses a shell script entrypoint. To run mosquitto utilities (mosquitto_passwd, mosquitto_pub, mosquitto_sub, etc.),
you must override the entrypoint:
# Run mosquitto_passwd
docker run --rm --entrypoint /usr/bin/mosquitto_passwd \
dhi.io/eclipse-mosquitto:<tag> -b /path/to/passwordfile username password
# Run mosquitto_pub
docker run --rm --entrypoint /usr/bin/mosquitto_pub \
dhi.io/eclipse-mosquitto:<tag> -h broker-host -t topic -m "message"
# Run mosquitto_sub
docker run --rm --entrypoint /usr/bin/mosquitto_sub \
dhi.io/eclipse-mosquitto:<tag> -h broker-host -t topic
# Run mosquitto_rr (request-response)
docker run --rm --entrypoint /usr/bin/mosquitto_rr \
dhi.io/eclipse-mosquitto:<tag> -h broker-host -t request-topic -t response-topic -m "request"
# Run mosquitto_ctrl
docker run --rm --entrypoint /usr/bin/mosquitto_ctrl \
dhi.io/eclipse-mosquitto:<tag> [ctrl-command]
The DHI image uses the following paths:
| Path | Purpose | Mount guidance |
|---|---|---|
/mosquitto/config | Configuration files (mosquitto.conf, password files, certs) | Mount as read-only when possible |
/mosquitto/data | Persistence for message queues and DB (if enabled) | Mount a writable volume for production |
/mosquitto/log | Broker logs | Mount if you need persistent logs |
All three directories exist in the image and are writable by the nonroot user. Mount volumes at these paths to persist data across container restarts.
When updating configuration files, you must restart the Mosquitto container for changes to take effect.
Mosquitto does not expose a standardized HTTP health endpoint by default. Use one of the following patterns for health checks:
Example Dockerfile HEALTHCHECK (add to a custom image if needed):
HEALTHCHECK --interval=30s --timeout=5s \
CMD ["/usr/bin/mosquitto_pub", "-h", "127.0.0.1", "-t", "health/check", "-m", "ping"] || exit 1
Note: The healthcheck command must override the entrypoint to run mosquitto_pub instead of the broker.
Docker Hardened Images come in different variants depending on their intended use. Image variants are identified by their tag.
Runtime variants are designed to run your application in production. These images are intended to be used either directly or as the FROM image in the final stage of a multi-stage build. These images typically:
Build-time variants typically include dev in the tag name and are intended for use in the first stage of a
multi-stage Dockerfile. These images typically:
To view the image variants and get more information about them, select the Tags tab for this repository, and then select a tag.
To migrate your application to a Docker Hardened Image, you must update your Dockerfile. At minimum, you must update the base image in your existing Dockerfile to a Docker Hardened Image. This and a few other common changes are listed in the following table of migration notes.
| Item | Migration note |
|---|---|
| Base image | Replace your base images in your Dockerfile with a Docker Hardened Image. |
| Package management | Non-dev images, intended for runtime, don't contain package managers. Use package managers only in images with a dev tag. |
| Non-root user | By default non-dev images, intended for runtime, run as the nonroot user. Ensure that necessary files and directories are accessible to the nonroot user. |
| Multi-stage build | Utilize images with a dev tag for build stages and non-dev images for runtime. To ensure that your final image is as minimal as possible, you should use a multi-stage build. |
| TLS certificates | Docker Hardened Images contain standard TLS certificates by default. There is no need to install TLS certificates. |
| Ports | Non-dev hardened images run as a nonroot user by default. As a result, applications in these images can't bind to privileged ports (below 1024) when running in Kubernetes or in Docker Engine versions older than 20. To avoid issues, configure your application to listen on port 1025 or higher inside the container. |
| Entry point | Docker Hardened Images may have different entry points than images such as Docker Official Images. Inspect entry points for Docker Hardened Images and update your Dockerfile if necessary. |
| No shell | By default, non-dev images, intended for runtime, don't contain a shell. Use dev images in build stages to run shell commands and then copy any necessary artifacts into the runtime stage. |
The following are common issues that you may encounter during migration.
The hardened images intended for runtime don't contain a shell nor any tools for debugging. The recommended method for debugging applications built with Docker Hardened Images is to use Docker Debug to attach to these containers. Docker Debug provides a shell, common debugging tools, and lets you install other tools in an ephemeral, writable layer that only exists during the debugging session.
By default image variants intended for runtime, run as the nonroot user. Ensure that necessary files and directories are accessible to the nonroot user. You may need to copy files to different directories or change permissions so your application running as the nonroot user can access them.
Non-dev hardened images run as a nonroot user by default. As a result, applications in these images can't bind to privileged ports (below 1024) when running in Kubernetes or in Docker Engine versions older than 20.10.
By default, image variants intended for runtime don't contain a shell. Use dev images in build stages to run shell
commands and then copy any necessary artifacts into the runtime stage. In addition, use Docker Debug to debug containers
with no shell.
Docker Hardened Images may have different entry points than images such as Docker Official Images. Use docker inspect
to inspect entry points for Docker Hardened Images and update your Dockerfile if necessary.