migrate
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
---
|
||||
- name: Docker volume backup
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: false
|
||||
|
||||
vars:
|
||||
backup_root: "/opt/docker-volume-backups"
|
||||
backup_timestamp: "{{ lookup('pipe', 'date +%Y%m%d-%H%M%S') }}"
|
||||
backup_archive_name: "backup_<< container_name >>_{{ backup_timestamp }}.tar.gz"
|
||||
|
||||
tasks:
|
||||
- name: Ensure backup root exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ backup_root }}"
|
||||
state: directory
|
||||
mode: "0750"
|
||||
|
||||
- name: Get container information
|
||||
community.docker.docker_container_info:
|
||||
name: "<< container_name >>"
|
||||
register: container_info
|
||||
|
||||
- name: Fail if container does not exist
|
||||
ansible.builtin.fail:
|
||||
msg: "Container '<< container_name >>' does not exist"
|
||||
when: not container_info.exists
|
||||
|
||||
- name: Record container running state
|
||||
ansible.builtin.set_fact:
|
||||
container_was_running: "{{ (container_info.container.State.Status | default('')) == 'running' }}"
|
||||
|
||||
- name: Stop container for consistent backup
|
||||
community.docker.docker_container:
|
||||
name: "<< container_name >>"
|
||||
state: stopped
|
||||
when:
|
||||
- stop_containers_during_backup | default(false)
|
||||
- container_was_running
|
||||
|
||||
- name: Back up container path using all attached volumes
|
||||
ansible.builtin.shell: |
|
||||
set -eu
|
||||
docker run --rm \
|
||||
--volumes-from "<< container_name >>" \
|
||||
-v "{{ backup_root }}":/backup \
|
||||
busybox sh -c '
|
||||
test -e "<< backup_container_path >>"
|
||||
tar -czf "/backup/{{ backup_archive_name }}" \
|
||||
-C / "<< backup_container_path | regex_replace('^/', '') >>"
|
||||
'
|
||||
args:
|
||||
executable: /bin/sh
|
||||
changed_when: true
|
||||
|
||||
- name: Start container after backup
|
||||
community.docker.docker_container:
|
||||
name: "<< container_name >>"
|
||||
state: started
|
||||
when:
|
||||
- stop_containers_during_backup | default(false)
|
||||
- container_was_running
|
||||
|
||||
- name: Remove old backup archives
|
||||
ansible.builtin.find:
|
||||
paths: "{{ backup_root }}"
|
||||
patterns: "backup_<< container_name >>_*.tar.gz"
|
||||
age: "<< backup_retention_days | default(14) >>d"
|
||||
recurse: true
|
||||
register: old_backups
|
||||
|
||||
- name: Delete old backup archives
|
||||
ansible.builtin.file:
|
||||
path: "{{ item.path }}"
|
||||
state: absent
|
||||
loop: "{{ old_backups.files }}"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
collections:
|
||||
- name: community.docker
|
||||
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"slug": "docker-volume-backup",
|
||||
"kind": "ansible",
|
||||
"metadata": {
|
||||
"name": "Docker Volume Backup",
|
||||
"description": "Backs up data from a Docker container path by auto-attaching all container volumes into a temporary backup container. Creates timestamped tar.gz archives with configurable retention.",
|
||||
"tags": [
|
||||
"docker",
|
||||
"backup",
|
||||
"volume",
|
||||
"container"
|
||||
],
|
||||
"icon": {
|
||||
"provider": "mdi",
|
||||
"id": "harddisk",
|
||||
"color": "emerald"
|
||||
},
|
||||
"draft": true,
|
||||
"version": {
|
||||
"name": "1",
|
||||
"source_dep_name": "manual/docker-volume-backup"
|
||||
}
|
||||
},
|
||||
"variables": [
|
||||
{
|
||||
"title": "Backup",
|
||||
"name": "backup",
|
||||
"items": [
|
||||
{
|
||||
"name": "container_name",
|
||||
"type": "str",
|
||||
"title": "Container Name",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "backup_retention_days",
|
||||
"type": "int",
|
||||
"title": "Retention Days",
|
||||
"required": false,
|
||||
"default": 14,
|
||||
"description": "Delete backup archives older than this many days",
|
||||
"config": {
|
||||
"slider": true,
|
||||
"min": 1,
|
||||
"max": 365,
|
||||
"step": 1,
|
||||
"placeholder": "14",
|
||||
"unit": "days"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "backup_container_path",
|
||||
"type": "str",
|
||||
"title": "Backup Path",
|
||||
"required": true,
|
||||
"description": "Path inside the container that should be archived"
|
||||
},
|
||||
{
|
||||
"name": "stop_containers_during_backup",
|
||||
"type": "bool",
|
||||
"title": "Stop Backup",
|
||||
"required": false,
|
||||
"default": false,
|
||||
"description": "If enabled, stop the container before backup and start it again afterwards if it was running"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Internal",
|
||||
"name": "internal",
|
||||
"items": [
|
||||
{
|
||||
"name": "backup_timestamp",
|
||||
"type": "str",
|
||||
"title": "Backup Timestamp",
|
||||
"required": false,
|
||||
"default": ""
|
||||
},
|
||||
{
|
||||
"name": "backup_root",
|
||||
"type": "str",
|
||||
"title": "Backup Root",
|
||||
"required": false,
|
||||
"default": "/backups",
|
||||
"config": {
|
||||
"placeholder": "/backups"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "backup_archive_name",
|
||||
"type": "str",
|
||||
"title": "Backup Archive Name",
|
||||
"required": false,
|
||||
"default": ""
|
||||
},
|
||||
{
|
||||
"name": "item",
|
||||
"type": "str",
|
||||
"title": "Loop Item",
|
||||
"required": false,
|
||||
"default": ""
|
||||
},
|
||||
{
|
||||
"name": "old_backups",
|
||||
"type": "str",
|
||||
"title": "Old Backups",
|
||||
"required": false,
|
||||
"default": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user