If I understand Docker correctly, it's not actually intended to be a sandbox and wasn't designed as such (e.g. the daemon runs as root, or at least used to). It's not clear to me what the threat model for running untrusted Docker images is, or how you'd know what the expected set of permissions were except by reading a README.
Whereas this feature is explicitly a sandboxing feature, and the needed permissions are enumerated by the service file.
Not that it's exactly relevant to this article, but on RHEL 8, at least, Docker isn't supported, and instead they use their own container runtime called Podman along with Buildah for building them.
Podman does not run as root, and thus neither do the containers.
I tested it out on my development backup laptop; I usually use Docker-CE on my main MBP. Podman and Buildah were able to deal with all my individual containers, but their replacement for Docker-Compose failed on all my compose environments, and the errors were not helpful. I ended up installing an unsupported version of Docker-CE, and everything worked fine.
Cgroups limit the impact anything inside the container can do to anything outside the container.
It doesn't matter that the daemon runs as root, it starts processes in an a way that prevents them from interacting with other daemons, filesystems, etc. resources.
It's not cgroups, but rather namespaces and seccomp (and apparmor/selinux on some distros) that sandbox the processes inside the container.
cgroups are used mostly for resource limits, not for sandboxing (aka namespacing).
docker by default does have a slightly more lax security posture than systemd or lxc (i.e. a default set of capabilities that isn't explicitly enumerated and a focus on UX over tweaking them, no usernamespaces by default, etc), though you're right that it is largely meant to be a secure sandbox for untrusted containers, as long as you know hat you're doing.
To quote Jessie's blog post [0]: "containers were not a top level design, they are something we build from Linux primitives [Linux namespaces and cgroups]".
cgroups can be used without namespaces, and the reverse is also true. Both of them are part of linux container implementations (like lxc and docker), but for an easy example, systemd uses cgroups for every service, and only uses namespaces for ones you very explicitly turn them on for.
Don't quote me on this, but I also think cgroups landed in the kernel many years before namespaces did.
Whereas this feature is explicitly a sandboxing feature, and the needed permissions are enumerated by the service file.