

As always you store data you want to keep in the volumes section.
With read-only you prevent new binaries from being added in the image space. You can add ‘noexec’ to your volumes/tmpfs preventing binaries to the areas that are writable. Then ideally you are using an image with minimal surface area (e.g., only sh and the exact binaries needed to make it go) and it’s very secure! It’s still plenty secure without a minimal image.
Not if you annotate your data volume with said ‘noexec’ which prevents execution from anything in the data volume. It looks like this, you can slam it on any volume you like - no volumes should have executables in them anyways.
Also I’m pretty sure ‘noexec’ is the default, so that’s by default protected. But I can’t confirm that from a quick search so not 100% on that.
‘/mnt/data:/container/place/it/wants:rw,noexec,nosuid,nodev,Z’
‘rw’ means read/write. You can change it to ‘ro’ for read-only if the volume shouldn’t write to it (maybe a config file).
Z is for selinux that means “only one program can read/write tho this”. You can change it to ‘z’ lowercase in case more than one needs to read/write. Only case I’ve found for little z is crowdsec needing to watch Caddy’s log for blocking.
So overall, the idea is that your volume mounts can’t be used to execute arbitrary binaries AND the image file system is frozen so that arbitrary binaries cannot be loaded into the image (which is by default all executable, a requirement to run anything in it). So if someone was able to hack into an internet-facing container, they won’t be able to load up whatever they want. They’ll be limited to what’s built into the image (which ideally are secure and limited in scope).