TL;DR -> Skip to "In a nutshell..." at the bottom.
Raw device and filesystem images (
.raw -- they all colloquially refer to the same general concept) are usually created with
dd, and you will find many, many examples of this online. For example:
dd if=/dev/sda2 of=fs.img
Will create an image of the filesystem on
/dev/sda2; on the pi this is usually the root filesystem (unless you are using NOOBs or some other multi-partition system). This can then be copied back out:
dd if=fs.img of=/dev/sda2
This concept is very copiously described over and over again online, particularly with reference to the pi, so I will not delve into the tweaks which might speed the process (namely, setting the block size via
bs=) except to say that they do not matter with regard to the state of the image itself, so you can try whatever you like.
Note that usually these discussions refer to copying the whole card (
/dev/sda) and not just the second partition (
I've used the latter arbitrarily to to introduce the distinction between "device" and "partition" (or filesystem; technically a partition is something that contains a filesystem, but for our purposes they are synonymous). With regard to the above example:
- Copying the image back to the partition will completely destroy whatever is on it, and you cannot do this on a running system where that is the root fs.
fs.img can't be on the filesystem in
/dev/sda2, because it will
- Run out of space.
- Change the content of what you are copying while you are copying it.
dd is very straightforward, and many people stop there because it is easy to understand and use.
Another option is copy/sync the filesystem contents (i.e., the files and directory hierarchies it contains), in which case if the system is running there are certain things you absolutely do not want to copy. The reasoning behind that is described here, with reference to maintaining a backup with
rsync, which is initially more complex than using
dd but also quicker and more flexible (for starters, you can update the backup from the running system without worrying about inconsistencies, and you don't have to copy all X GBs every time).
Creating a base image that you can redeploy later is pretty similar to maintaining a backup, except you don't need to maintain it as much, and you probably want to store it in an image format you can quickly copy to a card with
dd. There's a explanation of how pi oriented device images are structured here and here; the second one elaborates upon the first one and refers back to the answer about
rsync. If you read these you should be able to understand how to mount partitions from inside device images. When you do that, you can change the content of a filesystem, unmount it, and the content of the device image it is inside of will have changed.
So, you can do that with a virgin SD card image and
rsync your changes into it. This can be updated it at any point quickly, without having to shut the pi down or take the card out. You do need some attached or remote storage for the backup/base image, obviously.
In a nutshell, drawing from stuff in the above links, working from a running pi, and assuming we have the original
whatever.img from which you made your SD card on external / remote storage (since it won't fit on the card itself):
Mount the partitions using something like this (see that answer again, particularly if you get an "overlapping loop" error):
mount -v -o offset=4194304 -t vfat whatever.img /mnt/img/one
mount -v -o offset=62914560 -t ext4 whatever.img /mnt/img/two
Update the first parition, which is normally
rsync -aHv --delete /boot /mnt/img/one
Next the root fs:
rsync -axHv --delete / /mnt/img/two
x and make sure to actually read this to understand the significance.
Unmount both partitions and presto,
whatever.img is now updated to contain what you've added to the pi.