Compare commits
3 Commits
274a733dae
...
34d0c7a381
| Author | SHA1 | Date | |
|---|---|---|---|
| 34d0c7a381 | |||
| 46668163b7 | |||
| b335a0c9c0 |
77
backup.py
77
backup.py
@ -15,7 +15,8 @@ from datetime import datetime
|
||||
|
||||
|
||||
COMPOSE_PATH = Path('docker-compose.yml')
|
||||
BACKUP_PATH = Path('./data/bkp')
|
||||
BACKUP_VOL_PATH = Path('./backup/docker_named_volumes')
|
||||
BACKUP_SQL_PATH = Path('./backup/docker_sql_dumps')
|
||||
VOLUME_PREFIX = 'docker_'
|
||||
|
||||
|
||||
@ -53,6 +54,9 @@ def build_services_graph(services):
|
||||
def group_services(services, graph):
|
||||
grouped_services = {}
|
||||
for service in services:
|
||||
# Do not include if SQL
|
||||
if is_sql(services[service]):
|
||||
continue
|
||||
root = graph.find(service)
|
||||
if root not in grouped_services:
|
||||
grouped_services[root] = {'services': []}
|
||||
@ -65,32 +69,33 @@ def group_volumes(services, volumes, services_group):
|
||||
for group_name, group in services_group.items():
|
||||
group_volumes = group.setdefault('volumes', [])
|
||||
for service in group['services']:
|
||||
for volume in [v.split(':')[0] for v in services[service]['volumes']]:
|
||||
for volume in [v.split(':')[0] for v in services[service].get('volumes', [])]:
|
||||
if volume in volumes: group_volumes += [volume]
|
||||
|
||||
return services_group
|
||||
|
||||
def backup(volume):
|
||||
|
||||
def is_sql(service):
|
||||
return 'postgres' in service['image']
|
||||
|
||||
|
||||
def get_date_string():
|
||||
current_date = datetime.now()
|
||||
date_string = current_date.strftime("%Y-%m-%d")
|
||||
return current_date.strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
def backup_named_volume(volume):
|
||||
date_string = get_date_string()
|
||||
archive_name = f'{date_string}_{volume}.tar'
|
||||
print(f'backup volume {volume} to {BACKUP_PATH}/{archive_name}')
|
||||
print(f'backup volume {volume} to {BACKUP_VOL_PATH}/{archive_name}')
|
||||
|
||||
subprocess.run(f'docker run --rm --volume {VOLUME_PREFIX}{volume}:/data --volume {BACKUP_PATH.resolve()}:/bkp ubuntu tar -cf /bkp/{archive_name} -C /data .'.split())
|
||||
subprocess.run(f'docker run --rm --volume {VOLUME_PREFIX}{volume}:/data --volume {BACKUP_VOL_PATH.resolve()}:/bkp ubuntu tar -cf /bkp/{archive_name} -C /data .'.split())
|
||||
|
||||
|
||||
def run_docker_compose(cmd):
|
||||
subprocess.run(f'docker compose {cmd}'.split())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
with COMPOSE_PATH.open() as cf:
|
||||
compose = yaml.safe_load(cf)
|
||||
|
||||
services = compose['services']
|
||||
volumes = compose['volumes']
|
||||
def run_docker_compose(cmd): subprocess.run(f'docker compose {cmd}'.split())
|
||||
|
||||
|
||||
def backup_named_volumes(services, volumes):
|
||||
services_graph = build_services_graph(services)
|
||||
services_group = group_services(services, services_graph)
|
||||
services_group = group_volumes(services, volumes, services_group)
|
||||
@ -102,9 +107,45 @@ if __name__ == '__main__':
|
||||
print('no volumes')
|
||||
continue
|
||||
|
||||
print('run backup...')
|
||||
print(f'{group["volumes"]}: run backup...')
|
||||
|
||||
run_docker_compose(f'stop {" ".join(group["services"])}')
|
||||
for volume in group['volumes']:
|
||||
backup(volume)
|
||||
backup_named_volume(volume)
|
||||
run_docker_compose(f'start {" ".join(group["services"])}')
|
||||
|
||||
|
||||
def backup_sql_dumps(services, volumes):
|
||||
for service_name, service in services.items():
|
||||
if not is_sql(service):
|
||||
continue
|
||||
#print(f'Service {service_name} run sql dump...')
|
||||
backup_sql_dump(service_name, service)
|
||||
|
||||
|
||||
def backup_sql_dump(service_name, service):
|
||||
date_string = get_date_string()
|
||||
dump_name = f'{date_string}_{service_name}.sql'
|
||||
dump_path = BACKUP_SQL_PATH / dump_name
|
||||
|
||||
dump_path.parent.mkdir(exist_ok=True)
|
||||
|
||||
user = service['environment']['POSTGRES_USER']
|
||||
db = service['environment']['POSTGRES_DB']
|
||||
|
||||
print(f'Service {service_name} dump database to {dump_path}')
|
||||
|
||||
with dump_path.open('wb') as f:
|
||||
subprocess.run(f'docker compose exec -T {service_name} pg_dump -U {user} {db}'.split(),
|
||||
check=True,
|
||||
stdout=f)
|
||||
|
||||
if __name__ == '__main__':
|
||||
with COMPOSE_PATH.open() as cf:
|
||||
compose = yaml.safe_load(cf)
|
||||
|
||||
services = compose['services']
|
||||
volumes = compose['volumes']
|
||||
|
||||
backup_named_volumes(services, volumes)
|
||||
backup_sql_dumps(services, volumes)
|
||||
|
||||
@ -503,6 +503,15 @@ services:
|
||||
ENTE_APPS_CAST: https://tele-photos.guiotte.fr
|
||||
ENTE_APPS_EMBED_ALBUMS: https://capsule-photos.guiotte.fr
|
||||
ENTE_APPS_ACCOUNTS: https://comptes-photos.guiotte.fr
|
||||
ENTE_INTERNAL_ADMIN: 1580559962386438
|
||||
ENTE_INTERNAL_DISABLE_REGISTRATION: true
|
||||
ENTE_SMTP_HOST: ${MAIL_SERVER}
|
||||
ENTE_SMTP_PORT: ${MAIL_SMTP_PORT}
|
||||
ENTE_SMTP_USERNAME: ${MAIL_USERNAME}
|
||||
ENTE_SMTP_PASSWORD: ${MAIL_PASSWORD}
|
||||
ENTE_SMTP_SENDER_NAME: Ente
|
||||
ENTE_SMTP_EMAIL: ${MAIL_USERNAME}
|
||||
ENTE_SMTP_ENCRYPTION: ssl
|
||||
secrets:
|
||||
- ente-db-pw
|
||||
- ente-s3-key
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user