Skip to content

Commit 4b820a2

Browse files
committed
feat: add docker-volume script
1 parent c54c686 commit 4b820a2

3 files changed

Lines changed: 68 additions & 1 deletion

File tree

clit/docker.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from typing import List
77

88
from clit.config import JsonConfig
9-
from clit.files import existing_directory_type, shell, shell_find
9+
from clit.files import existing_directory_type, existing_file_type, shell, shell_find
1010
from clit.types import JsonDict
1111

1212
YML_DIRS = JsonConfig("docker-find-yml-dirs.json")
@@ -137,3 +137,68 @@ def docker_find():
137137
return
138138
args.chosen_function(parser, args)
139139
return
140+
141+
142+
def backup(parser, args):
143+
"""Backup a Docker volume."""
144+
for volume in args.volume_name:
145+
# TODO: when piping from stdin, stdout is printed only at the end (buffered)
146+
shell(
147+
"docker run --rm -i -v /var/lib/docker/volumes:/volumes -v {dir}:/backup busybox "
148+
"tar czf /backup/{volume}.tgz /volumes/{volume}".format(dir=args.backup_dir, volume=volume)
149+
)
150+
151+
152+
def restore(parser, args):
153+
"""Restore a Docker volume."""
154+
tgz_file: Path = args.tgz_file
155+
backup_dir = tgz_file.parent
156+
new_volume_name = args.volume_name if args.volume_name else tgz_file.stem
157+
158+
busybox = "docker run --rm -i -v /var/lib/docker:/docker -v {backup_dir}:/backup busybox ".format(
159+
backup_dir=backup_dir
160+
)
161+
162+
# Delete the destination directory before restoring
163+
shell(busybox + "rm -rf /docker/volumes/{new_volume_name}".format(new_volume_name=new_volume_name))
164+
165+
# Create the full path
166+
shell(busybox + "mkdir /docker/volumes/{new_volume_name}".format(new_volume_name=new_volume_name))
167+
168+
# Restore the .tgz file in the new empty directory
169+
shell(
170+
busybox
171+
+ "tar xzf /backup/{tgz} -C /docker/volumes/{new_volume_name}/ --strip-components 2".format(
172+
tgz=tgz_file.name, new_volume_name=new_volume_name
173+
)
174+
)
175+
176+
177+
# TODO: Convert to click
178+
def docker_volume():
179+
"""Backup and restore Docker volumes.
180+
181+
See also https://stackoverflow.com/a/23778599/1391315.
182+
"""
183+
parser = argparse.ArgumentParser(description="backup and restore Docker volumes")
184+
parser.set_defaults(chosen_function=None)
185+
subparsers = parser.add_subparsers(title="commands")
186+
187+
parser_backup = subparsers.add_parser("backup", aliases=["b"], help="backup a Docker volume")
188+
parser_backup.add_argument("backup_dir", type=existing_directory_type, help="directory to store the backups")
189+
parser_backup.add_argument("volume_name", nargs="+", help="Docker volume name")
190+
parser_backup.set_defaults(chosen_function=backup)
191+
192+
parser_restore = subparsers.add_parser("restore", aliases=["r"], help="restore a Docker volume")
193+
parser_restore.add_argument(
194+
"tgz_file", type=existing_file_type, help="full path of the .tgz file created by the 'backup' command"
195+
)
196+
parser_restore.add_argument("volume_name", nargs="?", help="volume name (default: basename of .tgz file)")
197+
parser_restore.set_defaults(chosen_function=restore)
198+
199+
args = parser.parse_args()
200+
if not args.chosen_function:
201+
parser.print_help()
202+
return
203+
args.chosen_function(parser, args)
204+
return

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ classifiers = [
2525
[tool.poetry.scripts]
2626
backup-full = "clit.files:backup_full"
2727
docker-find = "clit.docker:docker_find"
28+
docker-volume = "clit.docker:docker_volume"
2829
git-local-prune = "clit.git:prune_local_branches"
2930
git-vacuum = "clit.git:vacuum"
3031
pycharm-cli = "clit.dev:pycharm_cli"

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"console_scripts": [
2222
"backup-full = clit.files:backup_full",
2323
"docker-find = clit.docker:docker_find",
24+
"docker-volume = clit.docker:docker_volume",
2425
"git-local-prune = clit.git:prune_local_branches",
2526
"git-vacuum = clit.git:vacuum",
2627
"pycharm-cli = clit.dev:pycharm_cli",

0 commit comments

Comments
 (0)