<!doctype html>
< html lang = "en" class = "no-js" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width,initial-scale=1" >
< link rel = "canonical" href = "http://containrrr.github.io/watchtower/lifecycle-hooks/" >
< link rel = "shortcut icon" href = "../images/favicon.ico" >
< meta name = "generator" content = "mkdocs-1.1.2, mkdocs-material-6.2.3" >
< title > Lifecycle hooks - Watchtower< / title >
< link rel = "stylesheet" href = "../assets/stylesheets/main.3b61ea93.min.css" >
< link rel = "stylesheet" href = "../assets/stylesheets/palette.39b8e14a.min.css" >
< link rel = "preconnect" href = "https://fonts.gstatic.com" crossorigin >
< link rel = "stylesheet" href = "https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700%7CRoboto+Mono&display=fallback" >
< style > body , input { font-family : "Roboto" , - apple-system , BlinkMacSystemFont , Helvetica , Arial , sans-serif } code , kbd , pre { font-family : "Roboto Mono" , SFMono-Regular , Consolas , Menlo , monospace } < / style >
< link rel = "stylesheet" href = "../stylesheets/theme.css" >
< / head >
< body dir = "ltr" data-md-color-scheme = "containrrr" data-md-color-primary = "" data-md-color-accent = "" >
< input class = "md-toggle" data-md-toggle = "drawer" type = "checkbox" id = "__drawer" autocomplete = "off" >
< input class = "md-toggle" data-md-toggle = "search" type = "checkbox" id = "__search" autocomplete = "off" >
< label class = "md-overlay" for = "__drawer" > < / label >
< div data-md-component = "skip" >
< a href = "#executing_commands_before_and_after_updating" class = "md-skip" >
Skip to content
< / a >
< / div >
< div data-md-component = "announce" >
< / div >
< header class = "md-header" data-md-component = "header" >
< nav class = "md-header-nav md-grid" aria-label = "Header" >
< a href = "http://containrrr.github.io/watchtower/" title = "Watchtower" class = "md-header-nav__button md-logo" aria-label = "Watchtower" >
< img src = "../images/logo-450px.png" alt = "logo" >
< / a >
< label class = "md-header-nav__button md-icon" for = "__drawer" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" > < path d = "M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2z" / > < / svg >
< / label >
< div class = "md-header-nav__title" data-md-component = "header-title" >
< div class = "md-header-nav__ellipsis" >
< div class = "md-header-nav__topic" >
< span class = "md-ellipsis" >
Watchtower
< / span >
< / div >
< div class = "md-header-nav__topic" >
< span class = "md-ellipsis" >
Lifecycle hooks
< / span >
< / div >
< / div >
< / div >
< label class = "md-header-nav__button md-icon" for = "__search" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" > < path d = "M9.5 3A6.5 6.5 0 0116 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z" / > < / svg >
< / label >
< div class = "md-search" data-md-component = "search" role = "dialog" >
< label class = "md-search__overlay" for = "__search" > < / label >
< div class = "md-search__inner" role = "search" >
< form class = "md-search__form" name = "search" >
< input type = "text" class = "md-search__input" name = "query" aria-label = "Search" placeholder = "Search" autocapitalize = "off" autocorrect = "off" autocomplete = "off" spellcheck = "false" data-md-component = "search-query" data-md-state = "active" required >
< label class = "md-search__icon md-icon" for = "__search" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" > < path d = "M9.5 3A6.5 6.5 0 0116 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 019.5 16 6.5 6.5 0 013 9.5 6.5 6.5 0 019.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5z" / > < / svg >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" > < path d = "M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z" / > < / svg >
< / label >
< button type = "reset" class = "md-search__icon md-icon" aria-label = "Clear" data-md-component = "search-reset" tabindex = "-1" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" > < path d = "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" / > < / svg >
< / button >
< / form >
< div class = "md-search__output" >
< div class = "md-search__scrollwrap" data-md-scrollfix >
< div class = "md-search-result" data-md-component = "search-result" >
< div class = "md-search-result__meta" >
Initializing search
< / div >
< ol class = "md-search-result__list" > < / ol >
< / div >
< / div >
< / div >
< / div >
< / div >
< div class = "md-header-nav__source" >
< a href = "https://github.com/containrrr/watchtower/" title = "Go to repository" class = "md-source" >
< div class = "md-source__icon md-icon" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 448 512" > < path d = "M439.55 236.05L244 40.45a28.87 28.87 0 00-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 01-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-40.81z" / > < / svg >
< / div >
< div class = "md-source__repository" >
GitHub
< / div >
< / a >
< / div >
< / nav >
< / header >
< div class = "md-container" data-md-component = "container" >
< main class = "md-main" data-md-component = "main" >
< div class = "md-main__inner md-grid" >
< div class = "md-sidebar md-sidebar--primary" data-md-component = "navigation" >
< div class = "md-sidebar__scrollwrap" >
< div class = "md-sidebar__inner" >
< nav class = "md-nav md-nav--primary" aria-label = "Navigation" data-md-level = "0" >
< label class = "md-nav__title" for = "__drawer" >
< a href = "http://containrrr.github.io/watchtower/" title = "Watchtower" class = "md-nav__button md-logo" aria-label = "Watchtower" >
< img src = "../images/logo-450px.png" alt = "logo" >
< / a >
Watchtower
< / label >
< div class = "md-nav__source" >
< a href = "https://github.com/containrrr/watchtower/" title = "Go to repository" class = "md-source" >
< div class = "md-source__icon md-icon" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 448 512" > < path d = "M439.55 236.05L244 40.45a28.87 28.87 0 00-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 01-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 000 40.81l195.61 195.6a28.86 28.86 0 0040.8 0l194.69-194.69a28.86 28.86 0 000-40.81z" / > < / svg >
< / div >
< div class = "md-source__repository" >
GitHub
< / div >
< / a >
< / div >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = ".." class = "md-nav__link" >
Home
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../introduction/" class = "md-nav__link" >
Introduction
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../usage-overview/" class = "md-nav__link" >
Usage overview
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../arguments/" class = "md-nav__link" >
Arguments
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../notifications/" class = "md-nav__link" >
Notifications
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../container-selection/" class = "md-nav__link" >
Container selection
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../private-registries/" class = "md-nav__link" >
Private registries
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../linked-containers/" class = "md-nav__link" >
Linked containers
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../remote-hosts/" class = "md-nav__link" >
Remote hosts
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../secure-connections/" class = "md-nav__link" >
Secure connections
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "../stop-signals/" class = "md-nav__link" >
Stop signals
< / a >
< / li >
< li class = "md-nav__item md-nav__item--active" >
< input class = "md-nav__toggle md-toggle" data-md-toggle = "toc" type = "checkbox" id = "__toc" >
< label class = "md-nav__link md-nav__link--active" for = "__toc" >
Lifecycle hooks
< span class = "md-nav__icon md-icon" > < / span >
< / label >
< a href = "./" class = "md-nav__link md-nav__link--active" >
Lifecycle hooks
< / a >
< nav class = "md-nav md-nav--secondary" aria-label = "Table of contents" >
< label class = "md-nav__title" for = "__toc" >
< span class = "md-nav__icon md-icon" > < / span >
Table of contents
< / label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "#executing_commands_before_and_after_updating" class = "md-nav__link" >
Executing commands before and after updating
< / a >
< nav class = "md-nav" aria-label = "Executing commands before and after updating" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#specifying_update_commands" class = "md-nav__link" >
Specifying update commands
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#timeouts" class = "md-nav__link" >
Timeouts
< / a >
< nav class = "md-nav" aria-label = "Timeouts" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#pre-update_timeouts" class = "md-nav__link" >
Pre-update timeouts
< / a >
< / li >
< / ul >
< / nav >
< / li >
< li class = "md-nav__item" >
< a href = "#execution_failure" class = "md-nav__link" >
Execution failure
< / a >
< / li >
< / ul >
< / nav >
< / li >
< / ul >
< / nav >
< / li >
< li class = "md-nav__item" >
< a href = "../running-multiple-instances/" class = "md-nav__link" >
Running multiple instances
< / a >
< / li >
< / ul >
< / nav >
< / div >
< / div >
< / div >
< div class = "md-sidebar md-sidebar--secondary" data-md-component = "toc" >
< div class = "md-sidebar__scrollwrap" >
< div class = "md-sidebar__inner" >
< nav class = "md-nav md-nav--secondary" aria-label = "Table of contents" >
< label class = "md-nav__title" for = "__toc" >
< span class = "md-nav__icon md-icon" > < / span >
Table of contents
< / label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "#executing_commands_before_and_after_updating" class = "md-nav__link" >
Executing commands before and after updating
< / a >
< nav class = "md-nav" aria-label = "Executing commands before and after updating" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#specifying_update_commands" class = "md-nav__link" >
Specifying update commands
< / a >
< / li >
< li class = "md-nav__item" >
< a href = "#timeouts" class = "md-nav__link" >
Timeouts
< / a >
< nav class = "md-nav" aria-label = "Timeouts" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#pre-update_timeouts" class = "md-nav__link" >
Pre-update timeouts
< / a >
< / li >
< / ul >
< / nav >
< / li >
< li class = "md-nav__item" >
< a href = "#execution_failure" class = "md-nav__link" >
Execution failure
< / a >
< / li >
< / ul >
< / nav >
< / li >
< / ul >
< / nav >
< / div >
< / div >
< / div >
< div class = "md-content" >
< article class = "md-content__inner md-typeset" >
< a href = "https://github.com/containrrr/watchtower/edit/master/docs/lifecycle-hooks.md" title = "Edit this page" class = "md-content__button md-icon" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" > < path d = "M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z" / > < / svg >
< / a >
< h1 > Lifecycle hooks< / h1 >
< h2 id = "executing_commands_before_and_after_updating" > Executing commands before and after updating< a class = "headerlink" href = "#executing_commands_before_and_after_updating" title = "Permanent link" > ¶ < / a > < / h2 >
< blockquote >
< p > < strong > DO NOTE< / strong > : These are shell commands executed with < code > sh< / code > , and therefore require the
container to provide the < code > sh< / code > executable.< / p >
< / blockquote >
< p > It is possible to execute < em > pre/post-check< / em > and < em > pre/post-update< / em > commands
< strong > inside< / strong > every container updated by watchtower.< / p >
< ul >
< li > The < em > pre-check< / em > command is executed for each container prior to every update cycle.< / li >
< li > The < em > pre-update< / em > command is executed before stopping the container when an update is about to start.< / li >
< li > The < em > post-update< / em > command is executed after restarting the updated container< / li >
< li > The < em > post-check< / em > command is executed for each container post every update cycle.< / li >
< / ul >
< p > This feature is disabled by default. To enable it, you need to set the option
< code > --enable-lifecycle-hooks< / code > on the command line, or set the environment variable
< code > WATCHTOWER_LIFECYCLE_HOOKS< / code > to < code > true< / code > .< / p >
< h3 id = "specifying_update_commands" > Specifying update commands< a class = "headerlink" href = "#specifying_update_commands" title = "Permanent link" > ¶ < / a > < / h3 >
< p > The commands are specified using docker container labels, the following are currently available:< / p >
< table >
< thead >
< tr >
< th > Type< / th >
< th > Docker Container Label< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > Pre Check< / td >
< td > < code > com.centurylinklabs.watchtower.lifecycle.pre-check< / code > < / td >
< / tr >
< tr >
< td > Pre Update< / td >
< td > < code > com.centurylinklabs.watchtower.lifecycle.pre-update< / code > < / td >
< / tr >
< tr >
< td > Post Update< / td >
< td > < code > com.centurylinklabs.watchtower.lifecycle.post-update< / code > < / td >
< / tr >
< tr >
< td > Post Check< / td >
< td > < code > com.centurylinklabs.watchtower.lifecycle.post-check< / code > < / td >
< / tr >
< / tbody >
< / table >
< p > These labels can be declared as instructions in a Dockerfile (with some example .sh files):< / p >
< div class = "codehilite" > < pre > < span > < / span > < code > < span class = "k" > LABEL< / span > com.centurylinklabs.watchtower.lifecycle.pre-check< span class = "o" > =< / span > < span class = "s2" > " /sync.sh" < / span >
< span class = "k" > LABEL< / span > com.centurylinklabs.watchtower.lifecycle.pre-update< span class = "o" > =< / span > < span class = "s2" > " /dump-data.sh" < / span >
< span class = "k" > LABEL< / span > com.centurylinklabs.watchtower.lifecycle.post-update< span class = "o" > =< / span > < span class = "s2" > " /restore-data.sh" < / span >
< span class = "k" > LABEL< / span > com.centurylinklabs.watchtower.lifecycle.post-check< span class = "o" > =< / span > < span class = "s2" > " /send-heartbeat.sh" < / span >
< / code > < / pre > < / div >
< p > Or be specified as part of the < code > docker run< / code > command line:< / p >
< div class = "codehilite" > < pre > < span > < / span > < code > docker run -d < span class = "se" > \< / span >
--label< span class = "o" > =< / span > com.centurylinklabs.watchtower.lifecycle.pre-check< span class = "o" > =< / span > < span class = "s2" > " /sync.sh" < / span > < span class = "se" > \< / span >
--label< span class = "o" > =< / span > com.centurylinklabs.watchtower.lifecycle.pre-update< span class = "o" > =< / span > < span class = "s2" > " /dump-data.sh" < / span > < span class = "se" > \< / span >
--label< span class = "o" > =< / span > com.centurylinklabs.watchtower.lifecycle.post-update< span class = "o" > =< / span > < span class = "s2" > " /restore-data.sh" < / span > < span class = "se" > \< / span >
someimage
--label< span class = "o" > =< / span > com.centurylinklabs.watchtower.lifecycle.post-check< span class = "o" > =< / span > < span class = "s2" > " /send-heartbeat.sh" < / span > < span class = "se" > \< / span >
< / code > < / pre > < / div >
< h3 id = "timeouts" > Timeouts< a class = "headerlink" href = "#timeouts" title = "Permanent link" > ¶ < / a > < / h3 >
< p > The timeout for all lifecycle commands is 60 seconds. After that, a timeout will
occur, forcing Watchtower to continue the update loop.< / p >
< h4 id = "pre-update_timeouts" > Pre-update timeouts< a class = "headerlink" href = "#pre-update_timeouts" title = "Permanent link" > ¶ < / a > < / h4 >
< p > For the < code > pre-update< / code > lifecycle command, it is possible to override this timeout to
allow the script to finish before forcefully killing it. This is done by adding the
label < code > com.centurylinklabs.watchtower.lifecycle.pre-update-timeout< / code > followed by
the timeout expressed in minutes.< / p >
< p > If the label value is explicitly set to < code > 0< / code > , the timeout will be disabled. < / p >
< h3 id = "execution_failure" > Execution failure< a class = "headerlink" href = "#execution_failure" title = "Permanent link" > ¶ < / a > < / h3 >
< p > The failure of a command to execute, identified by an exit code different than
0, will not prevent watchtower from updating the container. Only an error
log statement containing the exit code will be reported.< / p >
< / article >
< / div >
< / div >
< / main >
< footer class = "md-footer" >
< div class = "md-footer-nav" >
< nav class = "md-footer-nav__inner md-grid" aria-label = "Footer" >
< a href = "../stop-signals/" class = "md-footer-nav__link md-footer-nav__link--prev" rel = "prev" >
< div class = "md-footer-nav__button md-icon" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" > < path d = "M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12z" / > < / svg >
< / div >
< div class = "md-footer-nav__title" >
< div class = "md-ellipsis" >
< span class = "md-footer-nav__direction" >
Previous
< / span >
Stop signals
< / div >
< / div >
< / a >
< a href = "../running-multiple-instances/" class = "md-footer-nav__link md-footer-nav__link--next" rel = "next" >
< div class = "md-footer-nav__title" >
< div class = "md-ellipsis" >
< span class = "md-footer-nav__direction" >
Next
< / span >
Running multiple instances
< / div >
< / div >
< div class = "md-footer-nav__button md-icon" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" > < path d = "M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4z" / > < / svg >
< / div >
< / a >
< / nav >
< / div >
< div class = "md-footer-meta md-typeset" >
< div class = "md-footer-meta__inner md-grid" >
< div class = "md-footer-copyright" >
Made with
< a href = "https://squidfunk.github.io/mkdocs-material/" target = "_blank" rel = "noopener" >
Material for MkDocs
< / a >
< / div >
< / div >
< / div >
< / footer >
< / div >
< script src = "../assets/javascripts/vendor.08c56446.min.js" > < / script >
< script src = "../assets/javascripts/bundle.6ced434e.min.js" > < / script > < script id = "__lang" type = "application/json" > { "clipboard.copy" : "Copy to clipboard" , "clipboard.copied" : "Copied to clipboard" , "search.config.lang" : "en" , "search.config.pipeline" : "trimmer, stopWordFilter" , "search.config.separator" : "[\\s\\-]+" , "search.placeholder" : "Search" , "search.result.placeholder" : "Type to start searching" , "search.result.none" : "No matching documents" , "search.result.one" : "1 matching document" , "search.result.other" : "# matching documents" , "search.result.more.one" : "1 more on this page" , "search.result.more.other" : "# more on this page" , "search.result.term.missing" : "Missing" } < / script >
< script >
app = initialize({
base: "..",
features: [],
search: Object.assign({
worker: "../assets/javascripts/worker/search.8c7e0a7e.min.js"
}, typeof search !== "undefined" & & search)
})
< / script >
< / body >
< / html >