Templates
Overview
You can customize the message posted by setting a notification template.
Notification Template
Sets the Go template used for formatting notification messages.
Argument: --notification-template
Environment Variable: WATCHTOWER_NOTIFICATION_TEMPLATE
Type: String
Default: See default templates belowNotification Template File
Sets the path to a file containing the Go template used for formatting notification messages.
Argument: --notification-template-file
Environment Variable: WATCHTOWER_NOTIFICATION_TEMPLATE_FILE
Type: String
Default: (empty)When both the notification-template and notification-template-file configuration options are specified, the file-based template takes precedence over the inline template.
Examples
Create a template file named custom-template.txt with your desired template content, then mount it into the container and specify the path:
services:
watchtower:
image: nickfedor/watchtower:latest
environment:
WATCHTOWER_NOTIFICATION_TEMPLATE_FILE: "/custom-template.txt"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /path/to/custom-template.txt:/custom-template.txtNotification Report
Enables the session report as the notification template data, including container statuses and logs.
Argument: --notification-report
Environment Variable: WATCHTOWER_NOTIFICATION_REPORT
Type: Boolean
Default: falseThe template is a Go template that processes either a list of log entries (Message, Data, Level, Time) captured from zerolog events or a notifications.Data struct, depending on the notification-report configuration option.
Simple Templates
Simple templates are used when the notification-report configuration option is not set, formatting individual log entries as they occur.
{{- range $i, $e := . -}}
{{- if $i}}{{- println -}}{{- end -}}
{{- $msg := $e.Message -}}
{{- if eq $msg "Found new image" -}}
Found new image: {{$e.Data.image}} ({{with $e.Data.new_id}}{{.}}{{else}}unknown{{end}})
{{- else if eq $msg "Stopping container" -}}
Stopped stale container: {{$e.Data.container}} ({{with $e.Data.id}}{{.}}{{else}}unknown{{end}})
{{- else if eq $msg "Started new container" -}}
Started new container: {{$e.Data.container}} ({{with $e.Data.new_id}}{{.}}{{else}}unknown{{end}})
{{- else if eq $msg "Removing image" -}}
Removed stale image: {{with $e.Data.image_id}}{{.}}{{else}}unknown{{end}}
{{- else if eq $msg "Detected multiple Watchtower instances - initiating cleanup" -}}
Detected {{$e.Data.count}} Watchtower instances - initiating cleanup
{{- else if $e.Data -}}
{{$msg}} | {{range $k, $v := $e.Data -}}{{$k}}={{$v}} {{- end}}
{{- else -}}
{{$msg}}
{{- end -}}
{{- end -}}- This template processes
info-level log entries in real-time, formatting key update events in past tense with container and image details from structured log fields. - It sends each event immediately in legacy mode, mimicking a step-by-step log.
Using Simple Templates in the Preview Tool
The Template Preview Tool uses a notifications.Data struct with .Entries as the log list.
{{- range $i, $e := .Entries -}} to match the data structure.{{- range $i, $e := .Entries -}}
{{- if $i}}{{- println -}}{{- end -}}
{{- $msg := $e.Message -}}
{{- if eq $msg "Found new image" -}}
Found new image: {{$e.Data.image}} ({{with $e.Data.new_id}}{{.}}{{else}}unknown{{end}})
{{- else if eq $msg "Stopping container" -}}
Stopped stale container: {{$e.Data.container}} ({{with $e.Data.id}}{{.}}{{else}}unknown{{end}})
{{- else if eq $msg "Started new container" -}}
Started new container: {{$e.Data.container}} ({{with $e.Data.new_id}}{{.}}{{else}}unknown{{end}})
{{- else if eq $msg "Removing image" -}}
Removed stale image: {{with $e.Data.image_id}}{{.}}{{else}}unknown{{end}}
{{- else if eq $msg "Detected multiple Watchtower instances - initiating cleanup" -}}
Detected {{$e.Data.count}} Watchtower instances - initiating cleanup
{{- else if $e.Data -}}
{{$msg}} | {{range $k, $v := $e.Data -}}{{$k}}={{$v}} {{- end}}
{{- else -}}
{{$msg}}
{{- end -}}
{{- end -}}Example output for a log entry with msg="Found new image":
Found new image: repo/image:latest (abcdef123456)Report Templates
When the notification-report configuration option is set, the template processes a notifications.Data struct containing a session report and log entries.
{{- if .Report -}}
{{- with .Report -}}
{{len .Scanned}} Scanned, {{len .Updated}} Updated, {{len .Restarted}} Restarted, {{len .Failed}} Failed
{{- if ( or .Updated .Restarted .Failed ) -}}
{{- range .Updated}}
- {{.Name}} ({{.ImageName}}): {{.CurrentImageID.ShortID}} updated to {{.LatestImageID.ShortID}}
{{- end -}}
{{- range .Fresh}}
- {{.Name}} ({{.ImageName}}): {{.State}}
{{- end -}}
{{- range .Restarted}}
- {{.Name}} ({{.ImageName}}): {{.State}}
{{- end -}}
{{- range .Skipped}}
- {{.Name}} ({{.ImageName}}): {{.State}}: {{.Error}}
{{- end -}}
{{- range .Failed}}
- {{.Name}} ({{.ImageName}}): {{.State}}: {{.Error}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if .Entries -}}
Logs:
{{- end -}}
{{range .Entries -}}{{.Time.Format "2006-01-02T15:04:05Z07:00"}} [{{.Level}}] {{.Message}}{{"\n"}}{{- end -}}
{{- end -}}- This template generates a summary of container statuses (scanned, updated, failed, etc.) followed by logs, used for notifications like email or Slack messages.
Example Usage
services:
watchtower:
image: nickfedor/watchtower:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
WATCHTOWER_NOTIFICATION_REPORT: "true"
WATCHTOWER_NOTIFICATION_URL: >
discord://token@channel
slack://watchtower@token-a/token-b/token-c
WATCHTOWER_NOTIFICATION_TEMPLATE: |
{{- if .Report -}}
{{- with .Report -}}
{{len .Scanned}} Scanned, {{len .Updated}} Updated, {{len .Restarted}} Restarted, {{len .Failed}} Failed
{{- if ( or .Updated .Restarted .Failed ) -}}
{{- range .Updated -}}
- {{.Name}} ({{.ImageName}}): {{.CurrentImageID.ShortID}} updated to {{.LatestImageID.ShortID}}
{{- end -}}
{{- range .Fresh -}}
- {{.Name}} ({{.ImageName}}): {{.State}}
{{- end -}}
{{- range .Restarted -}}
- {{.Name}} ({{.ImageName}}): {{.State}}
{{- end -}}
{{- range .Skipped -}}
- {{.Name}} ({{.ImageName}}): {{.State}}: {{.Error}}
{{- end -}}
{{- range .Failed -}}
- {{.Name}} ({{.ImageName}}): {{.State}}: {{.Error}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if .Entries -}}
Logs:
{{- end -}}
{{- range .Entries -}}{{.Time.Format "2006-01-02T15:04:05Z07:00"}} [{{.Level}}] {{.Message}}{{"\n"}}{{- end -}}
{{- end -}}Example output for a session with one updated container, one restarted container, and one error log:
5 Scanned, 1 Updated, 1 Restarted, 0 Failed
- /container (repo/image:latest): abcdef12 updated to 34567890
- /restarted-container (repo/image:latest): Restarted
Logs:
2025-08-20T06:00:13-07:00 [error] Operation failed. Try again later.Customizing Templates
You can create custom templates to format notifications differently.
Use the Template Preview Tool to test your templates interactively.
.Entries (e.g., {{- range $i, $e := .Entries -}}) to match the notifications.Data struct.Additional Resources
- For detailed template syntax, refer to the Go Template documentation.
- For log entry fields, each entry exposes
Message,Data(map of structured fields),Level, andTime(seepkg/notificationsnotification entries and zerolog).