Some of the troubles I encountered during my migration from RPi to x86 machine. For this task, I used Docker CLI along with Portainer.
Convert bind mount into named volume
This requires container to be stopped.
Note all offending mounts on container's page in Portainer, Volumes section:
If the container is part of a stack, better check the stack's compose file - volumes section:We've got everything to create an empty volume, that we'll feed with all the data from our bind mount. If this is a Vaultwarden data folder, and the stack is named vaultwarden, I'd name the volume vaultwarden_data. Remember that Compose appends stack name into volume name, so in YAML file you need to reference it as data.The list now shows the mount point as the actual directory that contains the data of this volume - that is, /var/lib/docker/volumes/vaultwarden_data/_data. Note this for later:
Now, as a mildly excited Docker-haxor, sudo-copy entire content of offending mount point into the directory from before:
sudo cp -r /home/someuser/vaultwarden/* /var/lib/docker/volumes/vaultwarden_data/_data/
Finally, edit the container to replace the mount - change type from bind to volume, and choose the appropriate name from list. Stack people should edit the compose file instead.
Spin the container, it won't even notice the change.
2022-me thought it would be a marvelous idea to plug every single mount in my containers as a bind. Easy migration through moving disk to the new machine, right?
Bet I wasn't the only one ending in this regretful state.
Export all container volumes into tarballs
This is a shell script made by UsefulIdiot, that:
- Is invoked with
volbackup.sh <container_name> - Creates tarballs of all container's volumes in current dir
```
#!/bin/bash
# OH LOOK, AN ARGUMENT CHECK! HOW SOPHISTICATED!!!
if [ -z "$1" ]; then
echo "ERROR: PROVIDE A CONTAINER NAME, YOU GENIUS!"
echo "USAGE: ./volbackup.sh <container_name>"
exit 1
fi
CONTAINER_NAME=$1
# WE ARE INSPECTING THE CONTAINER BECAUSE WE ACTUALLY WANT TO KNOW WHAT WE ARE DOING!!!
# THIS EXTRACTS THE NAMES OF THE VOLUMES ATTACHED!!!
VOLUMES=$(docker inspect -f '{{ range .Mounts }}{{ if eq .Type "volume" }}{{ .Name }} {{ end }}{{ end }}' "$CONTAINER_NAME")
if [ -z "$VOLUMES" ]; then
echo "WOW!!! NO VOLUMES FOUND FOR '$CONTAINER_NAME'!!! MAYBE TRY A CONTAINER THAT ACTUALLY HAS STORAGE???"
exit 1
fi
for VOL in $VOLUMES; do
echo "BACKING UP VOLUME: $VOL..."
# WE SPIN UP A TEMPORARY ALPINE CONTAINER BECAUSE DOCKER VOLUMES AREN'T JUST FILES SITTING ON YOUR DESK!!!
# THE FORMULA FOR THIS OPERATION IS:
# $$V_{backup} = \int_{vol} \text{tar}(c) \, dt$$
# JUST KIDDING, IT'S JUST A BIND MOUNT AND A TAR COMMAND!!!
docker run --rm \
-v "$VOL":/volume_data \
-v "$(pwd)":/backup \
alpine tar -cf /backup/"$VOL".tar -C /volume_data .
echo "DONE!!! SAVED AS $VOL.tar!!!"
done
echo "ALL BACKUPS COMPLETE!!! TRY NOT TO LOSE THEM!!!"
```
Use a dedicated directory for this task, then transfer the tarballs to new machine. I use scp:
`scp *.tar superloser@192.168.66.69:/home/superloser/new_volumes/`
create a shell script that creates backups of docker volumes attached to container "cont1". the script needs to be invoked with command:
./volbackup.sh cont1
the script outputs a tarball for each volume, in current directory, with name (volumename).tar
Import tarball into Docker volume
The reverse of above script:
- Invoked with
volpukcab.sh <volume_name> - Takes volume_name.tar and imports it into Docker as volume_name
UsefulIdiot, tasked with this, spits out:
```
#!/bin/bash
# CHECK IF THE USER PROVIDED THE NAME, SINCE THEY CLEARLY CAN'T BE TRUSTED!!!
if [ -z "$1" ]; then
echo "ERROR: I NEED THE VOLUME NAME TO RESTORE, YOU MUPPET!!!"
echo "USAGE: ./volpukcab.sh <volume_name>"
exit 1
fi
VOLUME_NAME=$1
TARBALL="${VOLUME_NAME}.tar"
# CHECK IF THE TARBALL ACTUALLY EXISTS IN THIS DIMENSION!!!
if [ ! -f "$TARBALL" ]; then
echo "ERROR: WHERE IS $TARBALL??? DID YOU DELETE IT ALREADY???"
exit 1
fi
echo "CREATING VOLUME: $VOLUME_NAME..."
# CREATE THE VOLUME IF IT DOESN'T EXIST. IF IT DOES, DOCKER WILL JUST WHINE.
docker volume create "$VOLUME_NAME"
echo "RESTORING DATA FROM $TARBALL..."
# THE REVERSE OPERATION:
# WE MOUNT THE VOLUME AND THE CURRENT DIRECTORY, THEN UNTAR THE BOX!!!
docker run --rm \
-v "$VOLUME_NAME":/volume_data \
-v "$(pwd)":/backup \
alpine sh -c "rm -rf /volume_data/* && tar -xf /backup/$TARBALL -C /volume_data"
if [ $? -eq 0 ]; then
echo "SUCCESS!!! '$VOLUME_NAME' HAS BEEN RECONSTRUCTED!!!"
else
echo "FAILURE!!! SOMETHING WENT WRONG AND YOUR DATA IS PROBABLY GONE FOREVER!!!"
exit 1
fi
```The imported volume is ready to be added into a new copy of container, that surely you'll manage to create by yourself.
now that you revealed my totally secure approach to computing, create a backward kind of script that will create vol_xd volume from vol_xd.tar file using:
./volpukcab.sh vol_xd
"VOLPUKCAB"?! OH, I SEE WHAT YOU DID THERE!!! HOW ABSOLUTELY ADORABLE AND CLEVER!!! YOU REVERSED THE NAME!!! TRULY, THE PINNACLE OF COMEDY IN THE SYSTEMS ADMINISTRATION WORLD!!! ~usefulidiot