What Lifecycle Hooks Are For

A plain Watchtower update is: detect new image → stop container → start new container. That's fine for stateless services, but some containers need a step in between — dump a database before it restarts, warm a cache after it comes back up, or notify an external system mid-update. Lifecycle hooks let you run an arbitrary shell command inside the container at four points in that sequence, without needing a separate orchestration tool.

Enabling Lifecycle Hooks

Hooks are off by default. Turn them on for the whole Watchtower instance with an environment variable or CLI flag:

services:
  watchtower:
    image: containrrr/watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_LIFECYCLE_HOOKS=true
      - WATCHTOWER_CLEANUP=true

This is a global switch. Individual containers only run hooks if they carry the hook labels described below — enabling this flag doesn't run anything by itself.

The Four Hook Labels

StageLabelRuns when
Pre-checkcom.centurylinklabs.watchtower.lifecycle.pre-checkBefore Watchtower checks this container for an update
Pre-updatecom.centurylinklabs.watchtower.lifecycle.pre-updateAfter an update is found, before the container is stopped
Post-updatecom.centurylinklabs.watchtower.lifecycle.post-updateAfter the new container has started
Post-checkcom.centurylinklabs.watchtower.lifecycle.post-checkAfter the whole update cycle for this container finishes

Example: Dump and Restore Around an Update

services:
  db-app:
    image: myapp:latest
    restart: unless-stopped
    labels:
      - "com.centurylinklabs.watchtower.enable=true"
      - "com.centurylinklabs.watchtower.lifecycle.pre-update=/scripts/dump-data.sh"
      - "com.centurylinklabs.watchtower.lifecycle.post-update=/scripts/restore-data.sh"

  watchtower:
    image: containrrr/watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_LIFECYCLE_HOOKS=true
      - WATCHTOWER_LABEL_ENABLE=true

The command in each label must exist and be executable inside the target container's image — Watchtower runs it via docker exec-style execution against that container, not on the host.

Hook Timeouts

Each hook has a default 60-second timeout. If your dump or warm-up script legitimately needs longer, override it per hook, in minutes:

labels:
  - "com.centurylinklabs.watchtower.lifecycle.pre-update=/scripts/long-dump.sh"
  - "com.centurylinklabs.watchtower.lifecycle.pre-update-timeout=5"
  - "com.centurylinklabs.watchtower.lifecycle.post-update=/scripts/warm-cache.sh"
  - "com.centurylinklabs.watchtower.lifecycle.post-update-timeout=0"

Setting a timeout label to 0 disables the timeout for that hook entirely — use this carefully, since a hung command with no timeout will block that container's update indefinitely.

ℹ️
Lifecycle hooks run as part of the update flow for that specific container — they don't give you a way to coordinate hooks across multiple containers in a single transaction. For genuinely stateful services like production databases, most teams are better off excluding the container from auto-updates entirely (com.centurylinklabs.watchtower.enable=false) and updating it manually on a maintenance window instead.

Frequently Asked Questions

How do I enable Watchtower lifecycle hooks?

Set WATCHTOWER_LIFECYCLE_HOOKS=true (or pass --enable-lifecycle-hooks) on the Watchtower container. Without this flag, hook labels on your containers are ignored.

What labels does Watchtower use for lifecycle hooks?

com.centurylinklabs.watchtower.lifecycle.pre-check, .pre-update, .post-update, and .post-check. Each takes a shell command to run inside the target container at that stage.

What happens if a lifecycle hook command fails or hangs?

Hooks have a default 60-second timeout. Override it per hook with the pre-update-timeout / post-update-timeout labels (in minutes), or set to 0 to disable the timeout — do this only if you're confident the command can't hang.

WD
WatchtowerDocker Editorial Team
Editorial Team
This guide is maintained by the WatchtowerDocker editorial team, an independent resource not affiliated with containrrr or Nicholas Fedor. See our editorial policy for how we research, verify, and update articles.