diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6c94276..84d14fe 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - repository: [restic-auto, telegraf, piwigo-souvenirs] + repository: [restic-auto, telegraf, piwigo-souvenirs, docker2mqtt] steps: - name: Checkout diff --git a/docker2mqtt/Dockerfile b/docker2mqtt/Dockerfile new file mode 100644 index 0000000..bfbf945 --- /dev/null +++ b/docker2mqtt/Dockerfile @@ -0,0 +1,15 @@ +FROM golang:alpine AS builder + +WORKDIR $GOPATH/src/napnap75/docker2mqtt/ + +COPY docker2mqtt.go . + +RUN apk add --no-cache git gcc musl-dev \ + && go mod init github.com/napnap75/multiarch-docker-images/docker2mqtt \ + && go get -d -v \ + && go build -ldflags="-w -s" -o /go/bin/docker2mqtt + +FROM alpine:latest + +COPY --from=builder /go/bin/docker2mqtt /usr/bin/ +ENTRYPOINT ["/usr/bin/docker2mqtt"] diff --git a/docker2mqtt/docker2mqtt.go b/docker2mqtt/docker2mqtt.go new file mode 100644 index 0000000..f8a5483 --- /dev/null +++ b/docker2mqtt/docker2mqtt.go @@ -0,0 +1,58 @@ +package main + +import ( + "context" + "flag" + "fmt" + "os" + "os/signal" + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" + "github.com/eclipse/paho.mqtt.golang" +) + +func main() { + // Handle interrupts to clean properly + c := make(chan os.Signal) + signal.Notify(c, os.Interrupt) + go func() { + select { + case sig := <-c: + fmt.Printf("Got %s signal. Aborting...\n", sig) + os.Exit(1) + } + }() + + // Load the parameters + var mqttServer = flag.String("mqtt-server", "tcp://localhost:1883", "The URL of the MQTT server to connecto to") + var mqttTopic = flag.String("mqtt-topic", "docker/events", "The MQTT topice to send the events to") + flag.Parse() + + // Connect to the docker socket + cli, err := client.NewClientWithOpts(client.FromEnv) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to connect to docker: %v\n", err) + return + } + ctx, _ := context.WithCancel(context.Background()) + + // Connect to the MQTT server + opts := mqtt.NewClientOptions().AddBroker(*mqttServer) + client := mqtt.NewClient(opts) + if token := client.Connect(); token.Wait() && token.Error() != nil { + fmt.Fprintf(os.Stderr, "Unable to connect to docker: %v\n", token.Error()) + return + } + + // Listen for events + msgs, errs := cli.Events(ctx, types.EventsOptions{}) + for { + select { + case err := <- errs: + fmt.Fprintf(os.Stderr, "Error while listening for docker events: %v\n", err) + + case msg := <-msgs: + client.Publish(*mqttTopic, 0, false, fmt.Sprintf("{ \"time\": %d, \"type\": \"%s\", \"name\": \"%s\", \"action\": \"%s\"}\n", msg.Time, msg.Type, msg.Actor.Attributes["name"], msg.Action)) + } + } +}