WIP
This commit is contained in:
106
backup/docker_outside.py
Executable file
106
backup/docker_outside.py
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import Iterable
|
||||
|
||||
import click
|
||||
import docker
|
||||
from docker.client import DockerClient
|
||||
from docker.errors import ContainerError
|
||||
from docker.models.containers import Container
|
||||
from rich.console import Console
|
||||
from rich.highlighter import NullHighlighter
|
||||
|
||||
console = Console(highlighter=NullHighlighter())
|
||||
print = console.print
|
||||
|
||||
client = docker.from_env()
|
||||
|
||||
|
||||
def get_project_containers(client: DockerClient, project_name: str):
|
||||
return client.containers.list(
|
||||
all=True,
|
||||
filters={'label': [f"com.docker.compose.project={project_name}"]}
|
||||
)
|
||||
|
||||
|
||||
def compose_start(client: DockerClient, project_name: str):
|
||||
print(f' DOCKER COMPOSE START {project_name} '.center(50, '='))
|
||||
for con in get_project_containers(client, project_name):
|
||||
try:
|
||||
print(f'Starting {con.name}...'.ljust(30), end='')
|
||||
con.start()
|
||||
except Exception as e:
|
||||
print('Failed')
|
||||
console.print_exception(e)
|
||||
else:
|
||||
print('[green]Done[/]')
|
||||
|
||||
|
||||
def compose_stop(client: DockerClient, project_name: str):
|
||||
print(f' DOCKER COMPOSE STOP {project_name} '.center(50, '='))
|
||||
for con in get_project_containers(client, project_name):
|
||||
try:
|
||||
print(f'Stopping {con.name}...'.ljust(30), end='')
|
||||
con.stop()
|
||||
except Exception as e:
|
||||
print('Failed')
|
||||
console.print_exception(e)
|
||||
else:
|
||||
print('[green]Done[/]')
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument('data_dir', type=click.Path(exists=True, file_okay=False, resolve_path=True, path_type=Path))
|
||||
@click.argument('repo',
|
||||
type=click.Path(exists=True, file_okay=False, resolve_path=True, path_type=Path),
|
||||
envvar='RESTIC_REPOSITORY')
|
||||
@click.option('-p', '--project')
|
||||
def run_backup_container(data_dir: Path, repo: Path, project: str):
|
||||
compose_stop(client, project_name=project)
|
||||
env = {
|
||||
'RESTIC_REPOSITORY': '/repo',
|
||||
'RESTIC_PASSWORD': os.environ['RESTIC_PASSWORD']
|
||||
}
|
||||
volumes = {
|
||||
"/var/run/docker.sock": {
|
||||
"bind": "/var/run/docker.sock",
|
||||
"mode": "rw"
|
||||
},
|
||||
data_dir.as_posix(): {
|
||||
"bind": '/data',
|
||||
"mode": "rw"
|
||||
},
|
||||
repo.as_posix(): {
|
||||
"bind": '/repo',
|
||||
"mode": "rw"
|
||||
},
|
||||
'/etc/localtime': {
|
||||
'bind': '/etc/localtime',
|
||||
'mode': 'ro'
|
||||
},
|
||||
'/etc/timezone': {
|
||||
'bind': '/etc/timezone',
|
||||
'mode': 'ro'
|
||||
}
|
||||
}
|
||||
# print(json.dumps(volumes, indent=4))
|
||||
print(f'Backing up\n{data_dir}\n to\n{repo}')
|
||||
|
||||
try:
|
||||
resp = client.containers.run(
|
||||
image='restic/restic:latest', remove=True,
|
||||
hostname=os.environ['HOSTNAME'],
|
||||
environment=env, volumes=volumes,
|
||||
command='backup /data --dry-run'
|
||||
).decode()
|
||||
print(resp)
|
||||
except ContainerError as e:
|
||||
print(e.stderr.decode())
|
||||
finally:
|
||||
compose_start(client, project_name=project)
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_backup_container()
|
||||
@@ -7,6 +7,10 @@ import click
|
||||
import docker
|
||||
import restic
|
||||
from docker.models.containers import Container
|
||||
from rich import print
|
||||
from rich.console import Console
|
||||
|
||||
console = Console()
|
||||
|
||||
client = docker.from_env()
|
||||
|
||||
@@ -48,13 +52,12 @@ def main(src: Path, docker_stop: str = None):
|
||||
else:
|
||||
cons = set()
|
||||
|
||||
pw_file = Path('/run/secrets/restic-pw').resolve()
|
||||
restic.password_file = pw_file.as_posix()
|
||||
|
||||
restic.backup(
|
||||
paths=[''],
|
||||
dry_run=True
|
||||
)
|
||||
with console.status(f'Running backup'):
|
||||
backup_result = restic.backup(
|
||||
paths=[src],
|
||||
dry_run=True
|
||||
)
|
||||
print(backup_result)
|
||||
|
||||
print(f'{len(restic.snapshots())} snapshots found in the repo')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user