Instalando o Mosquitto MQTT com Docker Compose

· 7 min de leitura ·atualizado em 15 de setembro de 2026

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á:

  1. Um broker MQTT protegido por usuário e senha
  2. Configurações, dados e logs armazenados em volumes Docker
  3. Um healthcheck para acompanhar a saúde do container
  4. Conexão com a rede Docker externa rt-network
  5. Uma base para integrar ESP32, Home Assistant e Zabbix

Pré-requisitos

Antes de começar, você precisa ter:

  1. Um servidor Linux com Docker instalado
  2. Docker Compose v2 ou superior
  3. A porta TCP 1883 livre no servidor
  4. Um usuário e uma senha forte para o broker MQTT
  5. A rede Docker externa rt-network criada 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:

  1. Ultron-vol-MQTT-config armazena a configuração e o arquivo de senhas
  2. Ultron-vol-MQTT-data armazena as mensagens persistentes do broker
  3. Ultron-vol-MQTT-log armazena 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ópicoFinalidade
ultron/aquario/temperaturaTemperatura atual em graus Celsius
ultron/aquario/statusEstado online ou offline do ESP32
ultron/aquario/alertaEstado do alerta de temperatura
ultron/aquario/telemetriaInformaçõ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

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!

// comentários