Indeed, this seems to work fine – with the emphasis on "seems".
To simplify the explanation, I assume a legacy filesystem without journaling (like ext2).
As soon as dd starts, the file
my_image.img is created. The information that this file exists and where it physically resides on the disk, is stored in the filesystem's index (think of it like a "table of contents"). The file's final size is not yet known, so it takes up a minimal default size (this is usually not shown to the user application).
As data is written to the file, it grows and the index is updated on regular intervals. However, the index resides on the disk, too. Once dd copied the index, the index in the copy is no longer updated. If you actually tried using the copy, you would notice that it is incomplete.
All this is academical of course, as dd cannot fit the full image file inside itself (unless you employ some kind of compression).
With commands like these, you can try it for yourself:
dd if=/dev/zero of=demo.raw bs=1M count=256 # create a dummy "partition" for demonstration
mkfs.ext4 demo.raw # create ext4 filesystem
target=$(mktemp -d) # create a temporary mountpoint
sudo mount demo.raw $target # mount the filesystem
sudo chown $USER $target # make filesystem root writable for current user
dd if=demo.raw of=$target/inner.raw bs=1M # copy fileystem into itself – error as expected (no space left on device)
dd if=demo.raw bs=1M | gzip -c > $target/inner.raw.gz # copy fileystem into itself, using compression
gzip -c $target/inner.raw.gz > inner.raw # decompress image
sudo mount inner.raw /mnt # mount inner copy – error as expected (copy is an incomplete file)
sudo umount $target
rm demo.raw inner.raw