From 0d470768c2438f2d096fffa3f14de8af2034596c Mon Sep 17 00:00:00 2001 From: "Chris (ChrisJr404)" <11917633+ChrisJr404@users.noreply.github.com> Date: Tue, 25 Aug 2026 13:09:33 -0400 Subject: [PATCH 1/3] Add one-of matching for stop-during-backup labels --- cmd/backup/config.go | 22 +++++ cmd/backup/stop_restart.go | 26 ++++-- cmd/backup/stop_restart_test.go | 85 +++++++++++++++++++ docs/how-tos/stop-containers-during-backup.md | 41 +++++++++ docs/reference/index.md | 8 ++ 5 files changed, 175 insertions(+), 7 deletions(-) diff --git a/cmd/backup/config.go b/cmd/backup/config.go index 692214da..b9243712 100644 --- a/cmd/backup/config.go +++ b/cmd/backup/config.go @@ -48,6 +48,7 @@ type Config struct { BackupStopContainerLabel string `split_words:"true"` BackupStopDuringBackupLabel string `split_words:"true" default:"true"` BackupStopDuringBackupNoRestartLabel string `split_words:"true" default:"true"` + LabelMatchBehavior MatchBehavior `split_words:"true" default:"match"` BackupStopServiceTimeout time.Duration `split_words:"true" default:"5m"` BackupFromSnapshot bool `split_words:"true"` BackupExcludeRegexp RegexpDecoder `split_words:"true"` @@ -120,6 +121,27 @@ func (c *CompressionType) String() string { return string(*c) } +// MatchBehavior controls how the value of a container's stop-during-backup +// label is matched against the value configured on this instance. With "match" +// the values have to be equal. With "one-of" the container's label value is +// split on commas so a single container can be targeted by multiple instances, +// each configured with a different value. +type MatchBehavior string + +func (l *MatchBehavior) Decode(v string) error { + switch v { + case "match", "one-of": + *l = MatchBehavior(v) + return nil + default: + return errwrap.Wrap(nil, fmt.Sprintf("error decoding label match behavior %s, expected one of \"match\" or \"one-of\"", v)) + } +} + +func (l *MatchBehavior) String() string { + return string(*l) +} + type CertDecoder struct { Cert *x509.Certificate } diff --git a/cmd/backup/stop_restart.go b/cmd/backup/stop_restart.go index 9ea4b384..c39426ff 100644 --- a/cmd/backup/stop_restart.go +++ b/cmd/backup/stop_restart.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "io" + "strings" "sync" "time" @@ -85,14 +86,25 @@ func isSwarm(c interface { return result.Info.Swarm.LocalNodeState != "" && result.Info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && result.Info.Swarm.ControlAvailable, nil } -func hasLabel(labels map[string]string, key, value string) bool { +func hasLabel(labels map[string]string, key, value string, matchBehavior MatchBehavior) bool { val, ok := labels[key] - return ok && val == value + if !ok { + return false + } + if matchBehavior == "one-of" { + for _, candidate := range strings.Split(val, ",") { + if strings.TrimSpace(candidate) == value { + return true + } + } + return false + } + return val == value } -func checkStopLabels(labels map[string]string, stopDuringBackupLabelValue string, stopDuringBackupNoRestartLabelValue string) (bool, bool, error) { - hasStopDuringBackupLabel := hasLabel(labels, "docker-volume-backup.stop-during-backup", stopDuringBackupLabelValue) - hasStopDuringBackupNoRestartLabel := hasLabel(labels, "docker-volume-backup.stop-during-backup-no-restart", stopDuringBackupNoRestartLabelValue) +func checkStopLabels(labels map[string]string, stopDuringBackupLabelValue string, stopDuringBackupNoRestartLabelValue string, matchBehavior MatchBehavior) (bool, bool, error) { + hasStopDuringBackupLabel := hasLabel(labels, "docker-volume-backup.stop-during-backup", stopDuringBackupLabelValue, matchBehavior) + hasStopDuringBackupNoRestartLabel := hasLabel(labels, "docker-volume-backup.stop-during-backup-no-restart", stopDuringBackupNoRestartLabelValue, matchBehavior) if hasStopDuringBackupLabel && hasStopDuringBackupNoRestartLabel { return hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, errwrap.Wrap(nil, "both docker-volume-backup.stop-during-backup and docker-volume-backup.stop-during-backup-no-restart have been set, cannot continue") } @@ -129,7 +141,7 @@ func (s *script) stopContainersAndServices() (func() error, error) { var containersToStop []handledContainer for _, c := range allContainers.Items { - hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(c.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel) + hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(c.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.LabelMatchBehavior) if err != nil { return noop, errwrap.Wrap(err, "error querying for containers to stop") } @@ -154,7 +166,7 @@ func (s *script) stopContainersAndServices() (func() error, error) { } for _, service := range allServices { - hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(service.Spec.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel) + hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(service.Spec.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.LabelMatchBehavior) if err != nil { return noop, errwrap.Wrap(err, "error querying for services to scale down") } diff --git a/cmd/backup/stop_restart_test.go b/cmd/backup/stop_restart_test.go index 36ec02d0..6961b6fd 100644 --- a/cmd/backup/stop_restart_test.go +++ b/cmd/backup/stop_restart_test.go @@ -19,6 +19,91 @@ func (m *mockInfoClient) Info(context.Context, client.InfoOptions) (client.Syste return m.result, m.err } +func TestHasLabel(t *testing.T) { + tests := []struct { + name string + labels map[string]string + key string + value string + matchBehavior MatchBehavior + expected bool + }{ + { + "match exact", + map[string]string{"docker-volume-backup.stop-during-backup": "service1"}, + "docker-volume-backup.stop-during-backup", + "service1", + "match", + true, + }, + { + "match mismatch", + map[string]string{"docker-volume-backup.stop-during-backup": "service2"}, + "docker-volume-backup.stop-during-backup", + "service1", + "match", + false, + }, + { + "match does not split", + map[string]string{"docker-volume-backup.stop-during-backup": "service1,service2"}, + "docker-volume-backup.stop-during-backup", + "service1", + "match", + false, + }, + { + "one-of first", + map[string]string{"docker-volume-backup.stop-during-backup": "service1,service2"}, + "docker-volume-backup.stop-during-backup", + "service1", + "one-of", + true, + }, + { + "one-of last with spaces", + map[string]string{"docker-volume-backup.stop-during-backup": "service1, service2"}, + "docker-volume-backup.stop-during-backup", + "service2", + "one-of", + true, + }, + { + "one-of no member", + map[string]string{"docker-volume-backup.stop-during-backup": "service1,service2"}, + "docker-volume-backup.stop-during-backup", + "service3", + "one-of", + false, + }, + { + "one-of single value", + map[string]string{"docker-volume-backup.stop-during-backup": "true"}, + "docker-volume-backup.stop-during-backup", + "true", + "one-of", + true, + }, + { + "label absent", + map[string]string{}, + "docker-volume-backup.stop-during-backup", + "true", + "one-of", + false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + result := hasLabel(test.labels, test.key, test.value, test.matchBehavior) + if result != test.expected { + t.Errorf("Expected %v, got %v", test.expected, result) + } + }) + } +} + func TestIsSwarm(t *testing.T) { tests := []struct { name string diff --git a/docs/how-tos/stop-containers-during-backup.md b/docs/how-tos/stop-containers-during-backup.md index e16eb7ec..fa17215e 100644 --- a/docs/how-tos/stop-containers-during-backup.md +++ b/docs/how-tos/stop-containers-during-backup.md @@ -35,6 +35,47 @@ volumes: data: ``` +## Target a single container from multiple backup instances + +A Docker label can only hold a single value per key, so a container can carry +only one `docker-volume-backup.stop-during-backup` value. If you run multiple +instances of this image with different `BACKUP_STOP_DURING_BACKUP_LABEL` values +and want the same container to be stopped by more than one of them, set +`LABEL_MATCH_BEHAVIOR` to `one-of`. The container's label value is then split on +commas and matches if any of the entries equals the configured value. + +```yml +services: + app: + # definition for app ... + labels: + - docker-volume-backup.stop-during-backup=service1,service2 + + backup-one: + image: offen/docker-volume-backup:v2 + environment: + BACKUP_STOP_DURING_BACKUP_LABEL: service1 + LABEL_MATCH_BEHAVIOR: one-of + volumes: + - data:/backup/my-app-backup:ro + - /var/run/docker.sock:/var/run/docker.sock:ro + + backup-two: + image: offen/docker-volume-backup:v2 + environment: + BACKUP_STOP_DURING_BACKUP_LABEL: service2 + LABEL_MATCH_BEHAVIOR: one-of + volumes: + - data:/backup/my-app-backup:ro + - /var/run/docker.sock:/var/run/docker.sock:ro + +volumes: + data: +``` + +The default value `match` keeps the previous behavior and requires the label +value to be equal to the configured value. + ## Stop containers during backup without restarting Sometimes you might want to stop containers for the backup but not have them start again automatically, for example if they are normally started by an external process or scheduler. diff --git a/docs/reference/index.md b/docs/reference/index.md index 32b47385..5e4e282b 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -555,6 +555,14 @@ If you need to confirm what the container actually loaded, see [Show loaded conf # skips restarting the container or service once the backup has finished. # BACKUP_STOP_DURING_BACKUP_NO_RESTART_LABEL="true" +# Controls how a container's stop-during-backup label value is matched against +# the value configured above. The default "match" requires the values to be +# equal. Setting this to "one-of" splits the container's label value on commas, +# so a single container labeled `stop-during-backup=service1,service2` can be +# stopped by multiple instances of this image, each configured with a different +# value. +# LABEL_MATCH_BEHAVIOR="match" + # When trying to scale down Docker Swarm services, give up after # the specified amount of time in case the service has not converged yet. # In case you need to adjust this timeout, supply a duration From cc90704b583771226422eb650cb949cdccbb180c Mon Sep 17 00:00:00 2001 From: "Chris (ChrisJr404)" <11917633+ChrisJr404@users.noreply.github.com> Date: Wed, 26 Aug 2026 14:34:59 -0400 Subject: [PATCH 2/3] Rename env var to BACKUP_LABEL_MATCH_BEHAVIOR for consistency --- cmd/backup/config.go | 2 +- cmd/backup/stop_restart.go | 4 ++-- docs/how-tos/stop-containers-during-backup.md | 6 +++--- docs/reference/index.md | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/backup/config.go b/cmd/backup/config.go index b9243712..97e85f57 100644 --- a/cmd/backup/config.go +++ b/cmd/backup/config.go @@ -48,7 +48,7 @@ type Config struct { BackupStopContainerLabel string `split_words:"true"` BackupStopDuringBackupLabel string `split_words:"true" default:"true"` BackupStopDuringBackupNoRestartLabel string `split_words:"true" default:"true"` - LabelMatchBehavior MatchBehavior `split_words:"true" default:"match"` + BackupLabelMatchBehavior MatchBehavior `split_words:"true" default:"match"` BackupStopServiceTimeout time.Duration `split_words:"true" default:"5m"` BackupFromSnapshot bool `split_words:"true"` BackupExcludeRegexp RegexpDecoder `split_words:"true"` diff --git a/cmd/backup/stop_restart.go b/cmd/backup/stop_restart.go index c39426ff..f13c839f 100644 --- a/cmd/backup/stop_restart.go +++ b/cmd/backup/stop_restart.go @@ -141,7 +141,7 @@ func (s *script) stopContainersAndServices() (func() error, error) { var containersToStop []handledContainer for _, c := range allContainers.Items { - hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(c.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.LabelMatchBehavior) + hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(c.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.BackupLabelMatchBehavior) if err != nil { return noop, errwrap.Wrap(err, "error querying for containers to stop") } @@ -166,7 +166,7 @@ func (s *script) stopContainersAndServices() (func() error, error) { } for _, service := range allServices { - hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(service.Spec.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.LabelMatchBehavior) + hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(service.Spec.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.BackupLabelMatchBehavior) if err != nil { return noop, errwrap.Wrap(err, "error querying for services to scale down") } diff --git a/docs/how-tos/stop-containers-during-backup.md b/docs/how-tos/stop-containers-during-backup.md index fa17215e..c33dbd0b 100644 --- a/docs/how-tos/stop-containers-during-backup.md +++ b/docs/how-tos/stop-containers-during-backup.md @@ -41,7 +41,7 @@ A Docker label can only hold a single value per key, so a container can carry only one `docker-volume-backup.stop-during-backup` value. If you run multiple instances of this image with different `BACKUP_STOP_DURING_BACKUP_LABEL` values and want the same container to be stopped by more than one of them, set -`LABEL_MATCH_BEHAVIOR` to `one-of`. The container's label value is then split on +`BACKUP_LABEL_MATCH_BEHAVIOR` to `one-of`. The container's label value is then split on commas and matches if any of the entries equals the configured value. ```yml @@ -55,7 +55,7 @@ services: image: offen/docker-volume-backup:v2 environment: BACKUP_STOP_DURING_BACKUP_LABEL: service1 - LABEL_MATCH_BEHAVIOR: one-of + BACKUP_LABEL_MATCH_BEHAVIOR: one-of volumes: - data:/backup/my-app-backup:ro - /var/run/docker.sock:/var/run/docker.sock:ro @@ -64,7 +64,7 @@ services: image: offen/docker-volume-backup:v2 environment: BACKUP_STOP_DURING_BACKUP_LABEL: service2 - LABEL_MATCH_BEHAVIOR: one-of + BACKUP_LABEL_MATCH_BEHAVIOR: one-of volumes: - data:/backup/my-app-backup:ro - /var/run/docker.sock:/var/run/docker.sock:ro diff --git a/docs/reference/index.md b/docs/reference/index.md index 5e4e282b..9ea2ec80 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -561,7 +561,7 @@ If you need to confirm what the container actually loaded, see [Show loaded conf # so a single container labeled `stop-during-backup=service1,service2` can be # stopped by multiple instances of this image, each configured with a different # value. -# LABEL_MATCH_BEHAVIOR="match" +# BACKUP_LABEL_MATCH_BEHAVIOR="match" # When trying to scale down Docker Swarm services, give up after # the specified amount of time in case the service has not converged yet. From fb2d928820380d26852b0185fde333f0557261c5 Mon Sep 17 00:00:00 2001 From: "Chris (ChrisJr404)" <11917633+ChrisJr404@users.noreply.github.com> Date: Wed, 2 Sep 2026 16:01:28 -0400 Subject: [PATCH 3/3] Make the one-of label match separator configurable --- cmd/backup/config.go | 6 ++-- cmd/backup/stop_restart.go | 17 ++++++----- cmd/backup/stop_restart_test.go | 29 ++++++++++++++++++- docs/how-tos/stop-containers-during-backup.md | 4 ++- docs/reference/index.md | 13 ++++++--- 5 files changed, 54 insertions(+), 15 deletions(-) diff --git a/cmd/backup/config.go b/cmd/backup/config.go index 97e85f57..460419b7 100644 --- a/cmd/backup/config.go +++ b/cmd/backup/config.go @@ -49,6 +49,7 @@ type Config struct { BackupStopDuringBackupLabel string `split_words:"true" default:"true"` BackupStopDuringBackupNoRestartLabel string `split_words:"true" default:"true"` BackupLabelMatchBehavior MatchBehavior `split_words:"true" default:"match"` + BackupLabelMatchSeparator string `split_words:"true" default:","` BackupStopServiceTimeout time.Duration `split_words:"true" default:"5m"` BackupFromSnapshot bool `split_words:"true"` BackupExcludeRegexp RegexpDecoder `split_words:"true"` @@ -124,8 +125,9 @@ func (c *CompressionType) String() string { // MatchBehavior controls how the value of a container's stop-during-backup // label is matched against the value configured on this instance. With "match" // the values have to be equal. With "one-of" the container's label value is -// split on commas so a single container can be targeted by multiple instances, -// each configured with a different value. +// split on BACKUP_LABEL_MATCH_SEPARATOR (a comma by default) so a single +// container can be targeted by multiple instances, each configured with a +// different value. type MatchBehavior string func (l *MatchBehavior) Decode(v string) error { diff --git a/cmd/backup/stop_restart.go b/cmd/backup/stop_restart.go index f13c839f..733214d2 100644 --- a/cmd/backup/stop_restart.go +++ b/cmd/backup/stop_restart.go @@ -86,13 +86,16 @@ func isSwarm(c interface { return result.Info.Swarm.LocalNodeState != "" && result.Info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && result.Info.Swarm.ControlAvailable, nil } -func hasLabel(labels map[string]string, key, value string, matchBehavior MatchBehavior) bool { +func hasLabel(labels map[string]string, key, value string, matchBehavior MatchBehavior, separator string) bool { val, ok := labels[key] if !ok { return false } if matchBehavior == "one-of" { - for _, candidate := range strings.Split(val, ",") { + if separator == "" { + separator = "," + } + for _, candidate := range strings.Split(val, separator) { if strings.TrimSpace(candidate) == value { return true } @@ -102,9 +105,9 @@ func hasLabel(labels map[string]string, key, value string, matchBehavior MatchBe return val == value } -func checkStopLabels(labels map[string]string, stopDuringBackupLabelValue string, stopDuringBackupNoRestartLabelValue string, matchBehavior MatchBehavior) (bool, bool, error) { - hasStopDuringBackupLabel := hasLabel(labels, "docker-volume-backup.stop-during-backup", stopDuringBackupLabelValue, matchBehavior) - hasStopDuringBackupNoRestartLabel := hasLabel(labels, "docker-volume-backup.stop-during-backup-no-restart", stopDuringBackupNoRestartLabelValue, matchBehavior) +func checkStopLabels(labels map[string]string, stopDuringBackupLabelValue string, stopDuringBackupNoRestartLabelValue string, matchBehavior MatchBehavior, separator string) (bool, bool, error) { + hasStopDuringBackupLabel := hasLabel(labels, "docker-volume-backup.stop-during-backup", stopDuringBackupLabelValue, matchBehavior, separator) + hasStopDuringBackupNoRestartLabel := hasLabel(labels, "docker-volume-backup.stop-during-backup-no-restart", stopDuringBackupNoRestartLabelValue, matchBehavior, separator) if hasStopDuringBackupLabel && hasStopDuringBackupNoRestartLabel { return hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, errwrap.Wrap(nil, "both docker-volume-backup.stop-during-backup and docker-volume-backup.stop-during-backup-no-restart have been set, cannot continue") } @@ -141,7 +144,7 @@ func (s *script) stopContainersAndServices() (func() error, error) { var containersToStop []handledContainer for _, c := range allContainers.Items { - hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(c.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.BackupLabelMatchBehavior) + hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(c.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.BackupLabelMatchBehavior, s.c.BackupLabelMatchSeparator) if err != nil { return noop, errwrap.Wrap(err, "error querying for containers to stop") } @@ -166,7 +169,7 @@ func (s *script) stopContainersAndServices() (func() error, error) { } for _, service := range allServices { - hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(service.Spec.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.BackupLabelMatchBehavior) + hasStopDuringBackupLabel, hasStopDuringBackupNoRestartLabel, err := checkStopLabels(service.Spec.Labels, s.c.BackupStopDuringBackupLabel, s.c.BackupStopDuringBackupNoRestartLabel, s.c.BackupLabelMatchBehavior, s.c.BackupLabelMatchSeparator) if err != nil { return noop, errwrap.Wrap(err, "error querying for services to scale down") } diff --git a/cmd/backup/stop_restart_test.go b/cmd/backup/stop_restart_test.go index 6961b6fd..d9e97989 100644 --- a/cmd/backup/stop_restart_test.go +++ b/cmd/backup/stop_restart_test.go @@ -26,6 +26,7 @@ func TestHasLabel(t *testing.T) { key string value string matchBehavior MatchBehavior + separator string expected bool }{ { @@ -34,6 +35,7 @@ func TestHasLabel(t *testing.T) { "docker-volume-backup.stop-during-backup", "service1", "match", + ",", true, }, { @@ -42,6 +44,7 @@ func TestHasLabel(t *testing.T) { "docker-volume-backup.stop-during-backup", "service1", "match", + ",", false, }, { @@ -50,6 +53,7 @@ func TestHasLabel(t *testing.T) { "docker-volume-backup.stop-during-backup", "service1", "match", + ",", false, }, { @@ -58,6 +62,7 @@ func TestHasLabel(t *testing.T) { "docker-volume-backup.stop-during-backup", "service1", "one-of", + ",", true, }, { @@ -66,6 +71,7 @@ func TestHasLabel(t *testing.T) { "docker-volume-backup.stop-during-backup", "service2", "one-of", + ",", true, }, { @@ -74,6 +80,7 @@ func TestHasLabel(t *testing.T) { "docker-volume-backup.stop-during-backup", "service3", "one-of", + ",", false, }, { @@ -82,6 +89,25 @@ func TestHasLabel(t *testing.T) { "docker-volume-backup.stop-during-backup", "true", "one-of", + ",", + true, + }, + { + "one-of custom separator", + map[string]string{"docker-volume-backup.stop-during-backup": "a,b|c,d"}, + "docker-volume-backup.stop-during-backup", + "c,d", + "one-of", + "|", + true, + }, + { + "one-of empty separator falls back to comma", + map[string]string{"docker-volume-backup.stop-during-backup": "service1,service2"}, + "docker-volume-backup.stop-during-backup", + "service2", + "one-of", + "", true, }, { @@ -90,13 +116,14 @@ func TestHasLabel(t *testing.T) { "docker-volume-backup.stop-during-backup", "true", "one-of", + ",", false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - result := hasLabel(test.labels, test.key, test.value, test.matchBehavior) + result := hasLabel(test.labels, test.key, test.value, test.matchBehavior, test.separator) if result != test.expected { t.Errorf("Expected %v, got %v", test.expected, result) } diff --git a/docs/how-tos/stop-containers-during-backup.md b/docs/how-tos/stop-containers-during-backup.md index c33dbd0b..0ef805cc 100644 --- a/docs/how-tos/stop-containers-during-backup.md +++ b/docs/how-tos/stop-containers-during-backup.md @@ -42,7 +42,9 @@ only one `docker-volume-backup.stop-during-backup` value. If you run multiple instances of this image with different `BACKUP_STOP_DURING_BACKUP_LABEL` values and want the same container to be stopped by more than one of them, set `BACKUP_LABEL_MATCH_BEHAVIOR` to `one-of`. The container's label value is then split on -commas and matches if any of the entries equals the configured value. +commas and matches if any of the entries equals the configured value. If your values +themselves contain a comma, set `BACKUP_LABEL_MATCH_SEPARATOR` to a different character +to split on instead. ```yml services: diff --git a/docs/reference/index.md b/docs/reference/index.md index 9ea2ec80..4889d735 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -557,12 +557,17 @@ If you need to confirm what the container actually loaded, see [Show loaded conf # Controls how a container's stop-during-backup label value is matched against # the value configured above. The default "match" requires the values to be -# equal. Setting this to "one-of" splits the container's label value on commas, -# so a single container labeled `stop-during-backup=service1,service2` can be -# stopped by multiple instances of this image, each configured with a different -# value. +# equal. Setting this to "one-of" splits the container's label value on +# BACKUP_LABEL_MATCH_SEPARATOR, so a single container labeled +# `stop-during-backup=service1,service2` can be stopped by multiple instances of +# this image, each configured with a different value. # BACKUP_LABEL_MATCH_BEHAVIOR="match" +# The separator used to split a container's label value when +# BACKUP_LABEL_MATCH_BEHAVIOR is "one-of". Defaults to a comma. Set it to a +# different character if your label values themselves contain a comma. +# BACKUP_LABEL_MATCH_SEPARATOR="," + # When trying to scale down Docker Swarm services, give up after # the specified amount of time in case the service has not converged yet. # In case you need to adjust this timeout, supply a duration