feat: Backup Secrets (copy secrets) #28

This commit is contained in:
Moritz 2023-09-22 16:39:40 +02:00
parent ebc0ea5d84
commit 5d4def6143
2 changed files with 28 additions and 3 deletions

View File

@ -9,9 +9,11 @@ import docker
import restic
from restic.errors import ResticFailedError
from pathlib import Path
from shutil import copyfile, rmtree
#logging.basicConfig(level=logging.INFO)
VOLUME_PATH = "/var/lib/docker/volumes/"
SECRET_PATH = '/secrets/'
SERVICE = None
@click.group()
@ -53,14 +55,15 @@ def export_secrets():
@cli.command()
def create():
pre_commands, post_commands, backup_paths, apps = get_backup_cmds()
copy_secrets(apps)
backup_paths.append(SECRET_PATH)
run_commands(pre_commands)
backup_volumes(backup_paths, apps)
run_commands(post_commands)
def get_backup_cmds():
client = docker.from_env()
containers = dict(map(lambda c: (
c.labels['com.docker.swarm.service.name'], c), client.containers.list()))
container_by_service = {c.labels['com.docker.swarm.service.name']: c for c in client.containers.list()}
backup_paths = set()
backup_apps = set()
pre_commands = {}
@ -73,7 +76,9 @@ def get_backup_cmds():
if SERVICE and SERVICE != stack_name:
continue
backup_apps.add(stack_name)
container = containers[s.name]
container = container_by_service.get(s.name)
if not container:
logging.error("Container {s.name} is not running, hooks can not be executed")
if prehook:= labels.get('backupbot.backup.pre-hook'):
pre_commands[container] = prehook
if posthook:= labels.get('backupbot.backup.post-hook'):
@ -82,6 +87,25 @@ def get_backup_cmds():
Path(VOLUME_PATH).glob(f"{stack_name}_*"))
return pre_commands, post_commands, list(backup_paths), list(backup_apps)
def copy_secrets(apps):
rmtree(SECRET_PATH, ignore_errors=True)
os.mkdir(SECRET_PATH)
client = docker.from_env()
container_by_service = {c.labels['com.docker.swarm.service.name']: c for c in client.containers.list()}
services = client.services.list()
for s in services:
app_name = s.attrs['Spec']['Labels']['com.docker.stack.namespace']
if app_name in apps:
if app_secs:= s.attrs['Spec']['TaskTemplate']['ContainerSpec'].get('Secrets'):
if not container_by_service.get(s.name):
logging.error("Container {s.name} is not running, secrets can not be copied.")
continue
container_id = container_by_service[s.name].id
for sec in app_secs:
src = f'/var/lib/docker/containers/{container_id}/mounts/secrets/{sec["SecretID"]}'
dst = SECRET_PATH + sec['SecretName']
copyfile(src, dst)
def run_commands(commands):
for container, command in commands.items():
if not command:

View File

@ -6,6 +6,7 @@ services:
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/var/lib/docker/volumes/:/var/lib/docker/volumes/"
- "/var/lib/docker/containers/:/var/lib/docker/containers/:ro"
- backups:/backups
environment:
- CRON_SCHEDULE