{"id":13464652,"url":"https://github.com/ccomb/buttervolume","last_synced_at":"2025-10-12T20:28:07.795Z","repository":{"id":19499355,"uuid":"77474636","full_name":"ccomb/buttervolume","owner":"ccomb","description":"BTRFS Volume plugin for Docker","archived":false,"fork":false,"pushed_at":"2024-11-05T17:09:28.000Z","size":212,"stargazers_count":85,"open_issues_count":19,"forks_count":11,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-12-05T16:02:29.553Z","etag":null,"topics":["btrfs","docker","plugin","volume"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ccomb.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGES.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-27T18:21:15.000Z","updated_at":"2024-11-30T22:46:40.000Z","dependencies_parsed_at":"2024-11-05T18:31:14.470Z","dependency_job_id":null,"html_url":"https://github.com/ccomb/buttervolume","commit_stats":{"total_commits":186,"total_committers":7,"mean_commits":"26.571428571428573","dds":0.08602150537634412,"last_synced_commit":"49cb7e0e8988898b09bdfb583963307a63b7dff3"},"previous_names":["anybox/buttervolume"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ccomb%2Fbuttervolume","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ccomb%2Fbuttervolume/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ccomb%2Fbuttervolume/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ccomb%2Fbuttervolume/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ccomb","download_url":"https://codeload.github.com/ccomb/buttervolume/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245454074,"owners_count":20617971,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["btrfs","docker","plugin","volume"],"created_at":"2024-07-31T14:00:48.049Z","updated_at":"2025-10-12T20:28:07.785Z","avatar_url":"https://github.com/ccomb.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":".. image:: https://travis-ci.org/ccomb/buttervolume.svg?branch=master\n   :target: https://travis-ci.org/ccomb/buttervolume\n   :alt: Travis state\n\n\nBTRFS Volume plugin for Docker\n==============================\n\n**What will Buttervolume allow you to do?**\n\n- Quickly recover recent data after an exploit or failure of your web sites or applications\n- Quickly rollback your data to a previous version after a failed upgrade\n- Implement automatic upgrade of your applications without fear\n- Keep an history of your data\n- Make many backups without consuming more disk space than needed\n- Build a resilient hosting cluster with data replication\n- Quickly move your applications between nodes\n- Create preconfigured or templated applications to deploy in seconds\n\n**What can Buttervolume do?**\n\n- Snapshot your Docker volumes\n- Restore a snapshot to its original volume or under a new volume\n- List and remove existing snapshots of your volumes\n- Clone your Docker volumes\n- Replicate or Sync your volumes to another host\n- Run periodic snapshots, sync or replication of your volumes\n- Remove your old snapshots periodically\n- Pause or resume the periodic jobs, either individually or globally\n\n**How does it work?**\n\nButtervolume is a Docker Volume Plugin that stores each Docker volume as a\nBTRFS subvolume.\n\n\n.. contents::\n\n\nIntroduction\n************\n\n`BTRFS \u003chttps://btrfs.wiki.kernel.org/\u003e`_ is a next-generation copy-on-write\nfilesystem with subvolume and snapshot support. A BTRFS `subvolume\n\u003chttps://btrfs.wiki.kernel.org/index.php/SysadminGuide#Subvolumes\u003e`_ can be\nseen as an independant file namespace that can live in a directory and can be\nmounted as a filesystem and snapshotted individually.\n\nOn the other hand, `Docker volumes\n\u003chttps://docs.docker.com/storage/volumes/\u003e`_ are commonly used\nto store persistent data of stateful containers, such as a MySQL/PostgreSQL\ndatabase or an upload directory of a CMS. By default, Docker volumes are just\nlocal directories in the host filesystem.  A number of `Volume plugins\n\u003chttps://docs.docker.com/engine/extend/legacy_plugins/#/volume-plugins\u003e`_\nalready exist for various storage backends, including distributed filesystems,\nbut small clusters often can't afford to deploy a distributed filesystem.\n\nWe believe BTRFS subvolumes are a powerful and lightweight storage solution for\nDocker volumes, allowing fast and easy replication (and backup) across several\nnodes of a small cluster.\n\nPrerequisites\n*************\n\nMake sure the directory ``/var/lib/buttervolume/`` is living in a BTRFS\nfilesystem. It can be a BTRFS mountpoint or a BTRFS subvolume or both.\n\n**Initial Setup**\n\nUse the ``buttervolume init`` command to easily set up the BTRFS environment::\n\n    # Default setup - checks /var/lib/buttervolume is on BTRFS and creates required directories\n    sudo buttervolume init\n    \n    # Custom BTRFS path - uses existing BTRFS filesystem at specified path\n    sudo buttervolume init --path /custom/btrfs/path\n    \n    # Image file - creates a new BTRFS image file\n    sudo buttervolume init --file /var/lib/docker/btrfs.img --size 20G\n\nThe init command must be run as root and automatically creates the required directory structure (config, ssh, volumes, snapshots).\n\n**Manual Setup (Alternative)**\n\nIf you prefer manual setup, create the directories for the config and ssh on the host::\n\n    sudo mkdir /var/lib/buttervolume\n    sudo mkdir /var/lib/buttervolume/config\n    sudo mkdir /var/lib/buttervolume/ssh\n\n\nBuild and run as a contributor\n******************************\n\nIf you want to be a contributor, read this chapter. Otherwise jump to the next section.\n\nYou first need to create a root filesystem for the plugin, using the provided Dockerfile::\n\n    git clone https://github.com/ccomb/buttervolume\n    ./build.sh\n\nBy default the plugin is built for the latest commit (HEAD). You can build another version by specifying it like this::\n\n    ./build.sh 3.7\n\nAt this point, you can set the SSH_PORT option for the plugin by running::\n\n    docker plugin set ccomb/buttervolume SSH_PORT=1122\n\nNote that this option is only relevant if you use the replication feature between two nodes.\n\nNow you can enable the plugin, which should start buttervolume in the plugin\ncontainer::\n\n    docker plugin enable ccomb/buttervolume:HEAD\n\nYou can check it is responding by running a buttervolume command using aliases::\n\n    export RUNCROOT=/run/docker/runtime-runc/plugins.moby/ # or /run/docker/plugins/runtime-root/plugins.moby/\n    alias drunc=\"sudo runc --root $RUNCROOT\"\n    alias buttervolume=\"drunc exec -t $(drunc list|tail -n+2|awk '{print $1}') buttervolume\"\n    buttervolume scheduled\n\nIncrease the log level by writing a `/var/lib/buttervolume/config/config.ini` file with::\n\n    [DEFAULT]\n    TIMER = 120\n\nThen check the logs with::\n\n    sudo journalctl -f -u docker.service\n\nYou can also locally install and run the plugin in the foreground with::\n\n    uv venv\n    uv sync --extra dev\n    sudo .venv/bin/buttervolume run\n\nThen you can use the buttervolume CLI that was installed in developer mode in the venv::\n\n    .venv/bin/buttervolume --version\n\n\nInstall and run as a user\n*************************\n\nIf the plugin is already pushed to the image repository, you can install it with::\n\n    docker plugin install ccomb/buttervolume\n\nCheck it is running::\n\n    docker plugin ls\n\nFind your runc root, then define useful aliases or functions.\n\n**Option 1: Using aliases (quick setup)**::\n\n    export RUNCROOT=/run/docker/runtime-runc/plugins.moby/ # or /run/docker/plugins/runtime-root/plugins.moby/\n    alias drunc=\"sudo runc --root $RUNCROOT\"\n    alias buttervolume=\"drunc exec -t $(drunc list|tail -n+2|awk '{print $1}') buttervolume\"\n\n**Option 2: Using functions (recommended for .bash_profile)**::\n\n    function drunc () {\n      RUNCROOT=/run/docker/runtime-runc/plugins.moby/ # or /run/docker/plugins/runtime-root/plugins.moby/\n      sudo runc --root $RUNCROOT $@\n    }\n    function buttervolume () {\n      drunc exec -t $(docker plugin ls --no-trunc  | grep 'ccomb/buttervolume:latest' |  awk '{print $1}') buttervolume $@\n    }\n\nAnd try a buttervolume command::\n\n    buttervolume scheduled\n\nOr create a volume with the driver. Note that the name of the driver is the\nname of the plugin::\n\n    docker volume create -d ccomb/buttervolume:latest myvolume\n\n\nUpgrade\n*******\n\nYou must force disable it before reinstalling it (as explained in the docker documentation)::\n\n    docker plugin disable -f ccomb/buttervolume\n    docker plugin rm -f ccomb/buttervolume\n    docker plugin install ccomb/buttervolume\n\n\nUsing buttervolume CLI in a container\n*************************************\n\nIf you need to run the buttervolume CLI from within a Docker container, you need to ensure proper access to the Docker daemon and plugin sockets.\n\n**Method 1: Mount required directories**::\n\n    docker run --rm -it \\\n      -v /var/run/docker.sock:/var/run/docker.sock \\\n      -v /run/docker/plugins:/run/docker/plugins \\\n      your-container-with-buttervolume buttervolume scheduled\n\n**Method 2: Override socket path**::\n\n    # If you know the exact socket path\n    docker run --rm -it \\\n      -v /var/run/docker.sock:/var/run/docker.sock \\\n      -v /run/docker/plugins:/run/docker/plugins \\\n      -e BUTTERVOLUME_SOCKET=/run/docker/plugins/\u003cplugin-id\u003e/btrfs.sock \\\n      your-container-with-buttervolume buttervolume scheduled\n\n**Creating a CLI container**::\n\n    # Dockerfile\n    FROM python:alpine\n    RUN pip install buttervolume\n    COPY --from=docker /usr/local/bin/docker /usr/local/bin/docker\n\n    # Usage\n    docker build -t buttervolume-cli .\n    docker run --rm -it \\\n      -v /var/run/docker.sock:/var/run/docker.sock \\\n      -v /run/docker/plugins:/run/docker/plugins \\\n      buttervolume-cli buttervolume scheduled\n\n\nMigrating existing Docker volumes\n**********************************\n\nTo migrate existing Docker volumes to buttervolume, the approach depends on whether your volumes are already on a BTRFS filesystem.\n\n**If /var/lib/docker/volumes is on the same BTRFS partition as /var/lib/buttervolume:**\n\nYou can efficiently move or snapshot existing volumes::\n\n    # Stop containers using the volumes first\n    docker stop \u003ccontainer-using-volume\u003e\n    \n    # Method 1: Move the volume (fastest)\n    sudo mv /var/lib/docker/volumes/\u003cvolume-name\u003e/_data /var/lib/buttervolume/volumes/\u003cvolume-name\u003e\n    \n    # Method 2: Create BTRFS snapshot (preserves original)\n    sudo btrfs subvolume snapshot /var/lib/docker/volumes/\u003cvolume-name\u003e/_data /var/lib/buttervolume/volumes/\u003cvolume-name\u003e\n\n**If /var/lib/docker/volumes is NOT on BTRFS:**\n\nYou need to copy the data::\n\n    # Stop containers using the volumes first\n    docker stop \u003ccontainer-using-volume\u003e\n    \n    # Create buttervolume and copy data\n    docker volume create -d ccomb/buttervolume:latest \u003cvolume-name\u003e\n    sudo cp -ar /var/lib/docker/volumes/\u003cvolume-name\u003e/_data/* /var/lib/buttervolume/volumes/\u003cvolume-name\u003e/\n    \n    # Remove old volume after verifying data integrity\n    docker volume rm \u003cvolume-name\u003e\n\n**Update your containers:**\n\nAfter migration, update your containers to use the new buttervolume driver::\n\n    # In docker-compose.yml\n    volumes:\n      my-data:\n        driver: ccomb/buttervolume:latest\n    \n    # Or with docker run\n    docker run -v my-data:/data --volume-driver=ccomb/buttervolume:latest myimage\n\n**Verification:**\n\nTest that your migrated volumes work correctly before removing the originals::\n\n    # Check volume exists\n    docker volume ls -f driver=ccomb/buttervolume:latest\n    \n    # Test with a temporary container\n    docker run --rm -v \u003cvolume-name\u003e:/test --volume-driver=ccomb/buttervolume:latest alpine ls -la /test\n\n\nConfigure\n*********\n\nYou can configure the following variables:\n\n    * ``DRIVERNAME``: the full name of the driver (with the tag)\n    * ``VOLUMES_PATH``: the path where the BTRFS volumes are located\n    * ``SNAPSHOTS_PATH``: the path where the BTRFS snapshots are located\n    * ``TEST_REMOTE_PATH``: the path during unit tests where the remote BTRFS snapshots are located\n    * ``SCHEDULE``: the path of the scheduler configuration\n    * ``RUNPATH``: the path of the docker run directory (/run/docker)\n    * ``SOCKET``: the path of the unix socket where buttervolume listens\n    * ``TIMER``: the number of seconds between two runs of the scheduler jobs\n    * ``DTFORMAT``: the format of the datetime in the logs\n    * ``LOGLEVEL``: the Python log level (INFO, DEBUG, etc.)\n\nThe configuration can be done in this order of priority:\n\n    #. from an environment variable prefixed with ``BUTTERVOLUME_`` (ex: ``BUTTERVOLUME_TIMER=120``)\n    #. from the [DEFAULT] section of the ``/etc/buttervolume/config.ini`` file\n       inside the container or ``/var/lib/buttervolume/config/config.ini`` on the\n       host\n\nExample of ``config.ini`` file::\n\n    [DEFAULT]\n    TIMER = 120\n\nIf none of this is configured, the following default values are used:\n\n    * ``DRIVERNAME = ccomb/buttervolume:latest``\n    * ``VOLUMES_PATH = /var/lib/buttervolume/volumes/``\n    * ``SNAPSHOTS_PATH = /var/lib/buttervolume/snapshots/``\n    * ``TEST_REMOTE_PATH = /var/lib/buttervolume/received/``\n    * ``SCHEDULE = /etc/buttervolume/schedule.csv``\n    * ``RUNPATH = /run/docker``\n    * ``SOCKET = $RUNPATH/plugins/btrfs.sock`` # only if run manually\n    * ``TIMER = 60``\n    * ``DTFORMAT = %Y-%m-%dT%H:%M:%S.%f``\n    * ``LOGLEVEL = INFO``\n\n\nUsage\n*****\n\nRunning the plugin\n------------------\n\nThe normal way to run it is as a new-style Docker Plugin as described above in\nthe \"Install and run\" section, which will start it automatically.  This will\ncreate a ``/run/docker/plugins/\u003cuuid\u003e/btrfs.sock`` file to be used by the\nDocker daemon. The ``\u003cuuid\u003e`` is the unique identifier of the `runc/OCI`\ncontainer running it.  This means you can probably run several versions of the\nplugin simultaneously but this is currently not recommended unless you keep in\nmind the volumes and snapshots are in the same place for the different\nversions. Otherwise you can configure a different path for the volumes and\nsnapshots of each different versions using the ``config.ini`` file.\n\nThen the name of the volume driver is the name of the plugin::\n\n    docker volume create -d ccomb/buttervolume:latest myvolume\n\nor::\n\n    docker volume create --volume-driver=ccomb/buttervolume:latest\n\nWhen creating a volume, you can choose to disable copy-on-write or enable compression\non a per-volume basis. Just use the `-o` or `--opt` option as defined in the `Docker documentation\n\u003chttps://docs.docker.com/engine/reference/commandline/volume_create/#options\u003e`_ ::\n\n    docker volume create -d ccomb/buttervolume -o copyonwrite=false myvolume\n    docker volume create -d ccomb/buttervolume -o compression=true myvolume\n    docker volume create -d ccomb/buttervolume -o compression=zlib myvolume\n\nAvailable options:\n\n- ``copyonwrite``: ``true`` (default) or ``false`` - enables/disables copy-on-write\n- ``compression``: ``false`` (default), ``true``, ``zlib``, ``lzo``, or ``zstd`` - enables BTRFS compression for new files\n\nCopy-On-Write is enabled by default. You can disable it if you really want.\nWhy disabling copy-on-write? If your docker volume stores databases such as\nPostgreSQL or MariaDB, the copy-on-write feature may hurt performance, though\nthe latest kernels have improved a lot. The good news is that disabling\ncopy-on-write does not prevent from doing snaphots.\n\nRunning the plugin locally or in legacy mode\n--------------------------------------------\n\nIf you installed it locally as a Python distribution, you can also\nstart it manually with::\n\n    sudo buttervolume run\n\nIn this case it will create a unix socket in ``/run/docker/plugins/btrfs.sock``\nfor use by Docker with the legacy plugin system. Then the name of the volume\ndriver is the name of the socket file::\n\n    docker volume create -d btrfs myvolume\n\nor::\n\n    docker create --volume-driver=btrfs\n\nWhen started, the plugin will also start its own scheduler to run periodic jobs\n(such as a snapshot, replication, purge or synchronization)\n\n\nCreating and deleting volumes\n-----------------------------\n\nOnce the plugin is running, whenever you create a container you can specify the\nvolume driver with ``docker create --volume-driver=ccomb/buttervolume --name \u003cname\u003e\n\u003cimage\u003e``.  You can also manually create a BTRFS volume with ``docker volume\ncreate -d ccomb/buttervolume``. It also works with docker-compose, by specifying the\n``ccomb/buttervolume`` driver in the ``volumes`` section of the compose file.\n\nWhen you delete the volume with ``docker rm -v \u003ccontainer\u003e`` or ``docker volume\nrm \u003cvolume\u003e``, the BTRFS subvolume is deleted. If you snapshotted the volume\nelsewhere in the meantime, the snapshots won't be deleted.\n\n\nManaging volumes and snapshots\n------------------------------\n\nWhen buttervolume is installed, it provides a command line tool\n``buttervolume``, with the following subcommands::\n\n    init                Initialize BTRFS filesystem for buttervolume\n    run                 Run the plugin in foreground\n    snapshot            Snapshot a volume\n    snapshots           List snapshots\n    schedule            Schedule, unschedule, pause or resume a periodic snapshot, replication, synchronization or purge\n    scheduled           List, pause or resume all the scheduled actions\n    restore             Restore a snapshot (optionally to a different volume)\n    clone               Clone a volume as new volume\n    send                Send a snapshot to another host\n    sync                Synchronise a volume from a remote host volume\n    rm                  Delete a snapshot\n    purge               Purge old snapshot using a purge pattern\n\n\nCreate a snapshot\n-----------------\n\nYou can create a readonly snapshot of the volume with::\n\n    buttervolume snapshot \u003cvolume\u003e\n\nThe volumes are currently expected to live in ``/var/lib/buttervolume/volumes`` and\nthe snapshot will be created in ``/var/lib/buttervolume/snapshots``, by appending the\ndatetime to the name of the volume, separated with ``@``.\n\n\nList the snapshots\n------------------\n\nYou can list all the snapshots::\n\n    buttervolume snapshots\n\nor just the snapshots corresponding to a volume with::\n\n    buttervolume snapshots \u003cvolume\u003e\n\n``\u003cvolume\u003e`` is the name of the volume, not the full path. It is expected\nto live in ``/var/lib/buttervolume/volumes``.\n\n\nRestore a snapshot\n------------------\n\nYou can restore a snapshot as a volume. The current volume will first\nbe snapshotted, deleted, then replaced with the snapshot.  If you provide a\nvolume name instead of a snapshot, the **latest snapshot** is restored. So no\ndata is lost if you do something wrong. Please take care of stopping the\ncontainer before restoring a snapshot::\n\n    buttervolume restore \u003csnapshot\u003e\n\n``\u003csnapshot\u003e`` is the name of the snapshot, not the full path. It is expected\nto live in ``/var/lib/buttervolume/snapshots``.\n\nBy default, the volume name corresponds to the volume the snapshot was created\nfrom. But you can optionally restore the snapshot to a different volume name by\nadding the target as the second argument::\n\n    buttervolume restore \u003csnapshot\u003e \u003cvolume\u003e\n\n\nClone a volume\n------------------\n\nYou can clone a volume as a new volume. The current volume will be cloned\nas a new volume name given as parameter. Please take care of stopping the\ncontainer before cloning a volume::\n\n    buttervolume clone \u003cvolume\u003e \u003cnew_volume\u003e\n\n``\u003cvolume\u003e`` is the name of the volume to be cloned, not the full path. It is expected\nto live in ``/var/lib/buttervolume/volumes``.\n``\u003cnew_volume\u003e`` is the name of the new volume to be created as clone of previous one,\nnot the full path. It is expected to be created in ``/var/lib/buttervolume/volumes``.\n\n\nDelete a snapshot\n-----------------\n\nYou can delete a snapshot with::\n\n    buttervolume rm \u003csnapshot\u003e\n\n``\u003csnapshot\u003e`` is the name of the snapshot, not the full path. It is expected\nto live in ``/var/lib/buttervolume/snapshots``.\n\n\nReplicate a snapshot to another host\n------------------------------------\n\nYou can incrementally send snapshots to another host, so that data is\nreplicated to several machines, allowing to quickly move a stateful docker\ncontainer to another host. The first snapshot is first sent as a whole, then\nthe next snapshots are used to only send the difference between the current one\nand the previous one. This allows to replicate snapshots very often without\nconsuming a lot of bandwith or disk space::\n\n    buttervolume send \u003chost\u003e \u003csnapshot\u003e\n\n``\u003csnapshot\u003e`` is the name of the snapshot, not the full path. It is expected\nto live in ``/var/lib/buttervolume/snapshots`` and is replicated to the same path on\nthe remote host.\n\n\n``\u003chost\u003e`` is the hostname or IP address of the remote host. The snapshot is\ncurrently sent using BTRFS send/receive through ssh, with an ssh server direcly\nincluded in the plugin. \n\n**SSH Configuration Requirements:**\n\n- SSH keys and configuration must be in ``/var/lib/buttervolume/ssh/`` (NOT in ``~/.ssh/``)\n- SSH keys must be present and authorized on target hosts  \n- Enable ``StrictHostKeyChecking no`` in ``/var/lib/buttervolume/ssh/config``\n- **Important**: Restart Docker daemons after any SSH configuration changes\n\nThe default SSH_PORT of the ssh server included in the plugin is **1122**. You can\nchange it with `docker plugin set ccomb/buttervolume SSH_PORT=\u003cPORT\u003e` before\nenabling the plugin.\n\nSynchronize a volume from another host volume\n---------------------------------------------\n\nYou can receive data from a remote volume, so in case there is a volume on\nthe remote host with the **same name**, it will get new and most recent data\nfrom the distant volume and replace in the local volume. Before running the\n``rsync`` command a snapshot is made on the local machine to manage recovery::\n\n    buttervolume sync \u003cvolume\u003e \u003chost1\u003e [\u003chost2\u003e][...]\n\nThe intent is to synchronize a volume between multi hosts on running\ncontainers, so you should schedule that action on each nodes from all remote\nhosts.\n\n.. note::\n\n   As we are pulling data from multiple hosts we never remove data, consider\n   removing scheduled actions before removing data on each hosts.\n\n.. warning::\n\n   Make sure your application is able to handle such synchronisation\n\n\nPurge old snapshots\n-------------------\n\nYou can purge old snapshot corresponding to the specified volume, using a retention pattern::\n\n    buttervolume purge \u003cpattern\u003e \u003cvolume\u003e\n\nIf you're unsure whether you retention pattern is correct, you can run the\npurge with the ``--dryrun`` option, to inspect what snapshots would be deleted,\nwithout deleting them::\n\n    buttervolume purge --dryrun \u003cpattern\u003e \u003cvolume\u003e\n\n``\u003cvolume\u003e`` is the name of the volume, not the full path. It is expected\nto live in ``/var/lib/buttervolume/volumes``.\n\n``\u003cpattern\u003e`` is the snapshot retention pattern. It is a semicolon-separated\nlist of time length specifiers with a unit. Units can be ``m`` for minutes,\n``h`` for hours, ``d`` for days, ``w`` for weeks, ``y`` for years. The pattern\nshould have at least 2 items.\n\nHere are a few examples of retention patterns:\n\n- ``4h:1d:2w:2y``\n    Keep all snapshots in the last four hours, then keep only one snapshot\n    every four hours during the first day, then one snapshot per day during\n    the first two weeks, then one snapshot every two weeks during the first\n    two years, then delete everything after two years.\n\n- ``4h:1w``\n    keep all snapshots during the last four hours, then one snapshot every\n    four hours during the first week, then delete older snapshots.\n\n- ``2h:2h``\n    keep all snapshots during the last two hours, then delete older snapshots.\n\n\nSchedule a job\n--------------\n\nYou can schedule, pause or resume a periodic job, such as a snapshot, a\nreplication, a synchronization or a purge. The schedule it self is stored in\n``/etc/buttervolume/schedule.csv``.\n\n**Schedule a snapshot** of a volume every 60 minutes::\n\n    buttervolume schedule snapshot 60 \u003cvolume\u003e\n\nPause this schedule::\n\n  buttervolume schedule snapshot pause \u003cvolume\u003e\n\nResume this schedule::\n\n  buttervolume schedule snapshot resume \u003cvolume\u003e\n\nRemove this schedule by specifying a timer of 0 min (or `delete`)::\n\n    buttervolume schedule snapshot 0 \u003cvolume\u003e\n\n**Schedule a replication** of volume ``foovolume`` to ``remote_host``::\n\n    buttervolume schedule replicate:remote_host 3600 foovolume\n\nRemove the same schedule::\n\n    buttervolume schedule replicate:remote_host 0 foovolume\n\n**Schedule a purge** every hour of the snapshots of volume ``foovolume``, but\nkeep all the snapshots in the last 4 hours, then only one snapshot every 4\nhours during the first week, then one snapshot every week during one year, then\ndelete all snapshots after one year::\n\n    buttervolume schedule purge:4h:1w:1y 60 foovolume\n\nRemove the same schedule::\n\n    buttervolume schedule purge:4h:1w:1y 0 foovolume\n\nUsing the right combination of snapshot schedule timer, purge schedule timer\nand purge retention pattern, you can create you own backup strategy, from the\nsimplest ones to more elaborate ones. A common one is the following::\n\n    buttervolume schedule snapshot 1440 \u003cvolume\u003e\n    buttervolume schedule purge:1d:4w:1y 1440 \u003cvolume\u003e\n\nIt should create a snapshot every day, then purge snapshots everydays while\nkeeping all snapshots in the last 24h, then one snapshot per day during one\nmonth, then one snapshot per month during only one year.\n\n**Schedule a syncrhonization** of volume ``foovolume`` from ``remote_host1``\nabd ``remote_host2``::\n\n    buttervolume schedule synchronize:remote_host1,remote_host2 60 foovolume\n\nRemove the same schedule::\n\n    buttervolume schedule synchronize:remote_host1,remote_host2 0 foovolume\n\n\nList, pause or resume all scheduled jobs\n----------------------------------------\n\nYou can list all the scheduled job with::\n\n    buttervolume scheduled\n\nor::\n\n    buttervolume scheduled list\n\nIt will display the schedule in the same format used for adding the schedule,\nwhich is convenient to remove an existing schedule or add a similar one.\n\nPause all the scheduled jobs::\n\n  buttervolume scheduled pause\n\nResume all the scheduled jobs::\n\n  buttervolume scheduled resume\n\nThe global job pause/resume feature is implemented separately from the\nindividual job pause/resume. So it will not affect your individual\npause/resume settings.\n\nCopy-on-write\n-------------\n\nCopy-On-Write is enabled by default. You can disable it if you really want.\n\nWhy disabling copy-on-write? If your docker volume stores databases such as\nPostgreSQL or MariaDB, the copy-on-write feature may hurt performance, though\nthe latest kernels have improved a lot. The good news is that disabling\ncopy-on-write does not prevent from doing snaphots.\n\n\nTesting\n*******\n\nIf your volumes directory is a BTRFS partition or volume, tests can be run\nwith::\n\n    ./test.sh\n\n\nWorking without a BTRFS partition\n*********************************\n\nIf you have no BTRFS partitions or volumes you can setup a virtual partition\nin a file as follows (tested on Debian 8):\n\nSetup BTRFS virtual partition::\n\n    sudo qemu-img create /var/lib/docker/btrfs.img 10G\n    sudo mkfs.btrfs /var/lib/docker/btrfs.img\n\n.. note::\n\n   you can ignore the error, in fact the new FS is formatted\n\nMount the partition somewhere temporarily to create 3 new BTRFS subvolumes::\n\n    sudo -s\n    mkdir /tmp/btrfs_mount_point\n    mount -o loop /var/lib/docker/btrfs.img /tmp/btrfs_mount_point/\n    btrfs subvolume create /tmp/btrfs_mount_point/snapshots\n    btrfs subvolume create /tmp/btrfs_mount_point/volumes\n    btrfs subvolume create /tmp/btrfs_mount_point/received\n    umount /tmp/btrfs_mount_point/\n    rm -r /tmp/btrfs_mount_point/\n\nStop docker, create required mount point and restart docker::\n\n    systemctl stop docker\n    mkdir -p /var/lib/buttervolume/volumes\n    mkdir -p /var/lib/buttervolume/snapshots\n    mkdir -p /var/lib/buttervolume/received\n    mount -o loop,subvol=volumes /var/lib/docker/btrfs.img /var/lib/buttervolume/volumes\n    mount -o loop,subvol=snapshots /var/lib/docker/btrfs.img /var/lib/buttervolume/snapshots\n    mount -o loop,subvol=received /var/lib/docker/btrfs.img /var/lib/buttervolume/received\n    systemctl start docker\n\nOnce you are done with your test, you can unmount those volumes and you will\nfind back your previous docker volumes::\n\n\n    systemctl stop docker\n    umount /var/lib/buttervolume/volumes\n    umount /var/lib/buttervolume/snapshots\n    umount /var/lib/buttervolume/received\n    systemctl start docker\n    rm /var/lib/docker/btrfs.img\n\n\nMigrate to version 3\n********************\n\nIf you're currently using Buttervolume 1.x or 2.0 in production, you must\ncarefully follow the guidelines below to migrate to version 3.\n\nFirst copy the ssh and config files and disable the scheduler::\n\n    sudo -s\n    docker cp buttervolume_plugin_1:/etc/buttervolume /var/lib/buttervolume/config\n    docker cp buttervolume_plugin_1:/root/.ssh /var/lib/buttervolume/ssh\n    mv /var/lib/buttervolume/config/schedule.csv /var/lib/buttervolume/config/schedule.csv.disabled\n\nThen stop all your containers, excepted buttervolume\n\nNow snapshot and delete all your volumes::\n\n    volumes=$(docker volume ls -f driver=ccomb/buttervolume:latest --format \"{{.Name}}\")\n    # or: # volumes=$(docker volume ls -f driver=ccomb/buttervolume:latest|tail -n+2|awk '{print $2}')\n    echo $volumes\n    for v in $volumes; do docker exec buttervolume_plugin_1 buttervolume snapshot $v; done\n    for v in $volumes; do docker volume rm $v; done\n\nThen stop the buttervolume container, **remove the old btrfs.sock file**, and\nrestart docker::\n\n    docker stop buttervolume_plugin_1\n    docker rm -v buttervolume_plugin_1\n    rm /run/docker/plugins/btrfs.sock\n    systemctl stop docker\n\nIf you were using Buttervolume 1.x, you must move your snapshots to the new location::\n\n    mkdir /var/lib/buttervolume/snapshots\n    cd /var/lib/docker/snapshots\n    for i in *; do btrfs subvolume snapshot -r $i /var/lib/buttervolume/snapshots/$i; done\n\nRestore /var/lib/docker/volumes as the original folder::\n\n    cd /var/lib/docker\n    mkdir volumes.new\n    mv volumes/* volumes.new/\n    umount volumes  # if this was a mounted btrfs subvolume\n    mv volumes.new/* volumes/\n    rmdir volumes.new\n    systemctl start docker\n\nChange your volume configurations (in your compose files) to use the new\n``ccomb/buttervolume:latest`` driver name instead of ``btrfs``\n\nThen start the new buttervolume 3.x as a managed plugin and check it is started::\n\n    docker plugin install ccomb/buttervolume:latest\n    docker plugin ls\n\nThen recreate all your volumes with the new driver and restore them from the snapshots::\n\n    for v in $volumes; do docker volume create -d ccomb/buttervolume:latest $v; done\n    export RUNCROOT=/run/docker/runtime-runc/plugins.moby/ # or /run/docker/plugins/runtime-root/plugins.moby/\n    alias drunc=\"sudo runc --root $RUNCROOT\"\n    alias buttervolume=\"drunc exec -t $(drunc list|tail -n+2|awk '{print $1}') buttervolume\"\n    # WARNING : check the the volume you will restore are the correct ones\n    for v in $volumes; do buttervolume restore $v; done\n\nThen restart your containers, check they are ok with the correct data.\n\nReenable the schedule::\n\n    mv /var/lib/buttervolume/config/schedule.csv.disabled /var/lib/buttervolume/config/schedule.csv\n\nCredits\n*******\n\nThanks to:\n\n- Christophe Combelles\n- Pierre Verkest\n- Marcelo Ochoa\n- Christoph Rist\n- Philip Nagler-Frank\n- Yoann MOUGNIBAS\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fccomb%2Fbuttervolume","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fccomb%2Fbuttervolume","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fccomb%2Fbuttervolume/lists"}