Files
file-backups/backup/docker_outside.py
John Lancaster b368cede93 WIP
2024-02-19 23:10:02 -06:00

107 lines
3.1 KiB
Python
Executable File

#!/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()