Skip to content

Docker: Schedule Jobs

In the other tutorials, we've looked at polling a HTTP server and building a Docker container, reading from a serial port, and publishing to the history database.

All these scripts were using an interval of a few seconds at most. Sometimes that's way too often. For example: Brewfather requires a minimum interval of 15 minutes.

Simply adding a sleep() call for 15 minutes is a very unreliable solution. If your service stops or crashes, it will cancel the interval, leading to very short or very long gaps.

A more practical solution is to use the schedule package.

Source code

On your Pi, create a new directory scheduledscript. in it, create two files:

script.py

py
"""
Code example for publishing data to the Brewblox eventbus on a fixed schedule

Dependencies:
- paho-mqtt
- schedule
"""

import json
from random import random
from time import sleep

import schedule
from paho.mqtt import client as mqtt

# 172.17.0.1 is the default IP address for the host running the Docker container
# Change this value if Brewblox is installed on a different computer
HOST = '172.17.0.1'

# 1883 is the default port for MQTT, but this can be changed in brewblox env settings.
PORT = 80

# This is a constant value. You never need to change it.
HISTORY_TOPIC = 'brewcast/history'

# The history service is subscribed to all topics starting with 'brewcast/history'
# We can make our topic more specific to help debugging
TOPIC = HISTORY_TOPIC + '/scheduledscript'

# Create the MQTT client
client = mqtt.Client()


def publish():

    try:
        client.connect_async(host=HOST, port=PORT)
        client.loop_start()

        # https://www.brewblox.com/dev/reference/history_events.html
        value = 20 + ((random() - 0.5) * 10)
        message = {
            'key': 'scheduledscript',
            'data': {'value[degC]': value}
        }

        client.publish(TOPIC, json.dumps(message))
        print(f'sent {message}')

    finally:
        client.loop_stop()


# For more examples on how to schedule tasks, see:
# https://github.com/dbader/schedule
schedule.every().minute.at(':05').do(publish)

while True:
    schedule.run_pending()
    sleep(1)

Dockerfile

FROM python:3.11-slim

COPY script.py /app/script.py

RUN pip3 install paho-mqtt schedule

CMD ["python3", "-u", "/app/script.py"]

Building

Your scheduledscript directory should look like this:

txt
.
├── script.py
└── Dockerfile

To build the image, run:

sh
docker build --tag scheduledscript scheduledscript/

Running

To run the built image:

sh
docker run --rm --tty scheduledscript

This is exactly the same as the command in the dockerized script tutorial.

Testing

It's often useful to listen in on what messages the eventbus actually received.

You can do so using https://mqtt-explorer.com/. Connect to mqtt://PI_ADDRESS:1883, and you can see all published events.