Instalando o Mosquitto MQTT com Docker Compose
Instalando o Mosquitto MQTT com Docker Compose
Introdução
O MQTT é um protocolo leve de troca de mensagens muito utilizado em automação residencial e projetos de Internet das Coisas. Um dispositivo publica uma mensagem em um tópico e todos os clientes inscritos nesse tópico recebem a informação.
Neste artigo, você vai instalar o Eclipse Mosquitto, um broker MQTT open source, usando Docker Compose. Essa instalação fará parte do projeto Ultron Aquário, que usará um ESP32 e um sensor DS18B20 para monitorar a temperatura de um aquário.
Ao final, você terá:
- Um broker MQTT protegido por usuário e senha
- Configurações, dados e logs armazenados em volumes Docker
- Um healthcheck para acompanhar a saúde do container
- Conexão com a rede Docker externa
rt-network - Uma base para integrar ESP32, Home Assistant e Zabbix
Pré-requisitos
Antes de começar, você precisa ter:
- Um servidor Linux com Docker instalado
- Docker Compose v2 ou superior
- A porta TCP
1883livre no servidor - Um usuário e uma senha forte para o broker MQTT
- A rede Docker externa
rt-networkcriada no ambiente
⚠️ Importante: a porta 1883 utiliza MQTT sem TLS. Não publique essa porta diretamente na internet. Mantenha o acesso restrito à sua rede local ou utilize uma VPN.
1. Verificando o Docker e o Docker Compose
Confirme se o Docker está instalado:
docker --version
Verifique também o Docker Compose:
docker compose version
Os dois comandos devem retornar as versões instaladas sem apresentar erros. Por exemplo, os números poderão ser diferentes no seu servidor:
Docker version 27.x.x, build ...
Docker Compose version v2.x.x
2. Conferindo a rede Docker externa
O container MQTT será conectado à rede externa rt-network, que já é utilizada
por outros serviços do ambiente. Verifique se ela existe, exibindo somente as
informações principais:
docker network inspect rt-network \
--format 'Nome: {{.Name}} | Driver: {{.Driver}} | Escopo: {{.Scope}}'
Se a rede ainda não existir, crie-a com:
docker network create --driver bridge rt-network
O resultado resumido deverá mostrar Nome: rt-network; o driver e o escopo
dependem da configuração do seu ambiente. Por exemplo:
Nome: rt-network | Driver: bridge | Escopo: local
💡 Dica: não execute o comando de criação se rt-network já estiver
configurada. O Compose apenas reutilizará essa rede e não tentará removê-la.
3. Criando o diretório do projeto
Crie o diretório que armazenará os arquivos da stack:
sudo mkdir -p /opt/docker/ultron-aquario
sudo chown "$USER":"$USER" /opt/docker/ultron-aquario
cd /opt/docker/ultron-aquario
pwd
O pwd deverá retornar /opt/docker/ultron-aquario. Depois de concluir as
próximas etapas, a estrutura do diretório ficará assim:
/opt/docker/ultron-aquario/
├── docker-compose.yml
├── .env
├── .env.example
└── .gitignore
4. Criando o arquivo de variáveis
Crie primeiro um modelo sem senha verdadeira:
nano .env.example
Adicione as variáveis abaixo:
MQTT_USERNAME=aquario-esp32
MQTT_PASSWORD=SUBSTITUA_POR_UMA_SENHA_LONGA_E_UNICA
MQTT_BIND_ADDRESS=0.0.0.0
MQTT_PORT=1883
Copie o modelo para .env, abra o arquivo e substitua a senha de exemplo por
uma senha longa e exclusiva:
cp .env.example .env
nano .env
chmod 600 .env
Confira somente o nome e as permissões, sem imprimir a senha:
ls -l .env
O início da linha deverá ser -rw-------, indicando que somente o proprietário
tem permissão de leitura e escrita.
⚠️ Importante: o ponto em .env apenas oculta o arquivo de uma listagem
ls comum. Não criptografa a senha. Nunca envie esse arquivo para o Git.
Se o diretório for versionado, adicione .env ao .gitignore:
printf '.env\n' >> .gitignore
O Docker Compose lê automaticamente .env quando ele está no diretório do
projeto, ao lado de docker-compose.yml. Não será necessário repetir
--env-file em todos os comandos. A senha também estará nas variáveis de
ambiente do container e será acessível a quem administra o Docker.
💡 Dica: se o servidor tiver um IP local fixo, substitua 0.0.0.0 pelo IP
da interface LAN. Assim, o Docker não publicará a porta MQTT em outras
interfaces do host.
5. Criando o Docker Compose
Crie o arquivo da stack:
nano docker-compose.yml
Adicione o conteúdo abaixo:
services:
ultron-mqtt:
image: eclipse-mosquitto:2.1.2-alpine
container_name: Ultron-MQTT
hostname: ultron-mqtt
restart: unless-stopped
environment:
MQTT_USERNAME: "${MQTT_USERNAME:?Defina MQTT_USERNAME no arquivo .env}"
MQTT_PASSWORD: "${MQTT_PASSWORD:?Defina MQTT_PASSWORD no arquivo .env}"
entrypoint:
- /bin/sh
- -ec
command:
- |
umask 077
cat > /mosquitto/config/mosquitto.conf <<'EOF'
per_listener_settings true
listener 1883 0.0.0.0
protocol mqtt
allow_anonymous false
password_file /mosquitto/config/password_file
persistence true
persistence_location /mosquitto/data/
autosave_interval 1800
log_dest stdout
log_dest file /mosquitto/log/mosquitto.log
log_timestamp true
log_type error
log_type warning
log_type notice
log_type information
connection_messages true
EOF
mosquitto_passwd -b -c /mosquitto/config/password_file "$${MQTT_USERNAME}" "$${MQTT_PASSWORD}"
chown -R mosquitto:mosquitto /mosquitto/config /mosquitto/data /mosquitto/log
exec /usr/sbin/mosquitto -c /mosquitto/config/mosquitto.conf
ports:
- "${MQTT_BIND_ADDRESS:-0.0.0.0}:${MQTT_PORT:-1883}:1883"
volumes:
- ultron-mqtt-config:/mosquitto/config
- ultron-mqtt-data:/mosquitto/data
- ultron-mqtt-log:/mosquitto/log
networks:
- rt-network
security_opt:
- no-new-privileges:true
healthcheck:
test:
- CMD-SHELL
- >-
mosquitto_pub -h 127.0.0.1 -p 1883
-u "$${MQTT_USERNAME}" -P "$${MQTT_PASSWORD}"
-t 'ultron/aquario/healthcheck' -m 'ping' -q 1 >/dev/null 2>&1
interval: 30s
timeout: 10s
retries: 3
start_period: 15s
logging:
driver: json-file
options:
max-size: 10m
max-file: "3"
networks:
rt-network:
name: rt-network
external: true
volumes:
ultron-mqtt-config:
name: Ultron-vol-MQTT-config
driver: local
ultron-mqtt-data:
name: Ultron-vol-MQTT-data
driver: local
ultron-mqtt-log:
name: Ultron-vol-MQTT-log
driver: local
6. Validando o arquivo Compose
Antes de criar o container, valide a configuração e a substituição das variáveis:
docker compose config --quiet && echo "Docker Compose validado com sucesso"
O resultado esperado é:
Docker Compose validado com sucesso
⚠️ Importante: evite publicar a saída de docker compose config sem
--quiet: ela pode mostrar a senha após substituir as variáveis do .env.
7. Iniciando o container MQTT
Baixe a imagem oficial antes da implantação:
docker compose pull
O resultado deverá indicar que a imagem do serviço ultron-mqtt foi baixada
(Pulled) ou já está atualizada.
Crie e inicie o container em segundo plano:
docker compose up -d
Na primeira execução, o Compose deverá informar que criou os volumes e iniciou
o container. Os nomes exibidos deverão incluir Ultron-vol-MQTT-config,
Ultron-vol-MQTT-data, Ultron-vol-MQTT-log e Ultron-MQTT.
Confira o estado do serviço:
docker compose ps
Para mostrar apenas os dados úteis do container:
docker ps --filter name=Ultron-MQTT \
--format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'
Depois do período inicial do healthcheck, a linha deverá mostrar o nome
Ultron-MQTT, a imagem eclipse-mosquitto:2.1.2-alpine, a porta 1883 e o
estado healthy. Por exemplo:
NAMES IMAGE STATUS PORTS
Ultron-MQTT eclipse-mosquitto:2.1.2-alpine Up 1 minute (healthy) 0.0.0.0:1883->1883/tcp
Se aparecer health: starting, espere alguns segundos e consulte novamente.
8. Verificando os logs e os volumes
Acompanhe os logs do Mosquitto:
docker logs --tail 30 Ultron-MQTT
Você deverá ver linhas informando que o broker iniciou e abriu a porta 1883.
Uma delas costuma conter Opening ipv4 listen socket on port 1883.
Para acompanhar os logs continuamente, use docker logs --follow Ultron-MQTT e
pressione Ctrl+C para sair sem interromper o container.
Confira os volumes criados:
docker volume ls --filter name=Ultron-vol-MQTT
Você deverá encontrar:
Ultron-vol-MQTT-config
Ultron-vol-MQTT-data
Ultron-vol-MQTT-log
Os três volumes possuem funções diferentes:
Ultron-vol-MQTT-configarmazena a configuração e o arquivo de senhasUltron-vol-MQTT-dataarmazena as mensagens persistentes do brokerUltron-vol-MQTT-logarmazena os registros de funcionamento
9. Testando publicação e assinatura
O MQTT usa o conceito de publish/subscribe. O Mosquitto não oferece uma interface gráfica própria. Para ver as mensagens, abra um terminal que ficará inscrito nos tópicos do aquário:
docker exec -it Ultron-MQTT sh -c \
'mosquitto_sub -h 127.0.0.1 -u "$MQTT_USERNAME" -P "$MQTT_PASSWORD" -t "ultron/aquario/#" -v'
O comando ficará aguardando mensagens. Em outro terminal, publique uma mensagem de teste:
docker exec Ultron-MQTT sh -c \
'mosquitto_pub -h 127.0.0.1 -u "$MQTT_USERNAME" -P "$MQTT_PASSWORD" -t "ultron/aquario/teste" -m "MQTT funcionando"'
O primeiro terminal deverá apresentar:
ultron/aquario/teste MQTT funcionando
O comando de publicação não mostra texto quando funciona; a confirmação
aparece no terminal do assinante. Pressione Ctrl+C para encerrar a assinatura.
O healthcheck também publica ultron/aquario/healthcheck ping a cada 30
segundos; essa linha adicional é esperada.
Se aparecer Connection Refused: not authorised, confira o usuário e a senha
definidos no .env e recrie o container:
docker compose up -d --force-recreate
💡 Dica: o # acompanha todos os tópicos abaixo de ultron/aquario/. Isso
mostra o fluxo em tempo real, não um histórico completo. O broker pode guardar
o último valor de um tópico quando ele é publicado com a opção retain.
10. Comandos de manutenção
Para reiniciar o broker:
docker compose restart ultron-mqtt
Para parar a stack sem excluir o container:
docker compose stop
Para remover o container e preservar os volumes:
docker compose down
⚠️ Importante: não acrescente --volumes ao comando down, pois essa opção
remove os volumes persistentes e pode causar perda de dados.
Para atualizar a imagem e recriar o container:
docker compose pull
docker compose up -d
11. Tópicos do monitoramento do aquário
O projeto usará uma estrutura previsível de tópicos:
| Tópico | Finalidade |
|---|---|
ultron/aquario/temperatura | Temperatura atual em graus Celsius |
ultron/aquario/status | Estado online ou offline do ESP32 |
ultron/aquario/alerta | Estado do alerta de temperatura |
ultron/aquario/telemetria | Informações de diagnóstico do dispositivo |
O ESP32 publicará a temperatura e o estado como mensagens retidas. Também será
configurada uma mensagem Last Will and Testament, permitindo que o broker
publique offline se o dispositivo perder a conexão inesperadamente.
Considerações finais
Com o Mosquitto executando no container Ultron-MQTT, o projeto já possui uma
camada de comunicação leve, persistente e compatível com o Home Assistant. A
próxima etapa será conectar o ESP32 ao broker, publicar as leituras do DS18B20 e
criar o sensor MQTT no Home Assistant.
Em um próximo artigo, mostrarei como realizar essa mesma implantação utilizando uma stack pela interface do Portainer.
Referências
- Imagem oficial Eclipse Mosquitto no Docker Hub
- Documentação do Eclipse Mosquitto
- Documentação do Docker Compose
Agradeço por ler esse artigo e espero vê-lo novamente em breve. Continue nos acompanhando para mais conteúdo relevante e inspirador. Até a próxima!