In terms of the daemon model of Docker, I guess it does look a bit complicated, and is not explained very well.
In production you will do docker run -d nginx, not run it in the foreground, so the client (docker) process is not really in the picture - if you run in the foreground it is just there to stream the standard IO, and so you can kill the process with ^C from the shell.
The docker daemon (dockerd) is there to listen for new requests, but since 1.11 it no longer runs containers. Since 1.12 you can restart it without killing your containers (with the right config option) see https://docs.docker.com/engine/admin/live-restore/
so you can eg do a daemon upgrade without downtime. It is still handling some things, eg logs, so it is best if it does restart.
The process that actually runs containers is containerd. This is a very simple daemon with a grpc socket interface. That uses runc (the OCI standard runner) but that does not stay running, only a small process called containerd-shim does, which is there to act as a parent for the actual container process, so that containerd can be restarted.
You can use containerd as a runtime, with runc containers, but runc is not that user friendly. You can use https://github.com/jfrazelle/riddler to get something you can run from a docker container. You could also use runc from systemd if you want. However runc doesnt do a lot of setup, eg the layered filesystem handling is all part of how dockerd sets things up for runc, so you would have to do that yourself if you dont want to waste a lot of disk space.
It does sound a bit complicated, but it is just separation of concerns and breaking up the once monolithic docker binary into a client and a set of servers that all do smaller tasks and which can be restarted independently.
Such structures can be hard to document with both clarity and brevity. Take a look at how Wietse Venema describes the elements of Postfix, for a nuanced masterclass in the art. http://www.postfix.org/OVERVIEW.html
Both the architecture and the approach to documenting it were pioneered by Bernstein's qmail, which is the first Unix program of comparable ambition to be structured in this way --- it's crazy to think that there was a time when this implementation strategy was groundbreaking, but, it was.
(Fun fact: Venema and Bernstein had a long-running feud, and Postfix exists pretty much entirely because Venema appreciated qmail's architecture but couldn't stomach working with anything Bernstein produced.)
In production you will do docker run -d nginx, not run it in the foreground, so the client (docker) process is not really in the picture - if you run in the foreground it is just there to stream the standard IO, and so you can kill the process with ^C from the shell.
The docker daemon (dockerd) is there to listen for new requests, but since 1.11 it no longer runs containers. Since 1.12 you can restart it without killing your containers (with the right config option) see https://docs.docker.com/engine/admin/live-restore/ so you can eg do a daemon upgrade without downtime. It is still handling some things, eg logs, so it is best if it does restart.
The process that actually runs containers is containerd. This is a very simple daemon with a grpc socket interface. That uses runc (the OCI standard runner) but that does not stay running, only a small process called containerd-shim does, which is there to act as a parent for the actual container process, so that containerd can be restarted.
You can use containerd as a runtime, with runc containers, but runc is not that user friendly. You can use https://github.com/jfrazelle/riddler to get something you can run from a docker container. You could also use runc from systemd if you want. However runc doesnt do a lot of setup, eg the layered filesystem handling is all part of how dockerd sets things up for runc, so you would have to do that yourself if you dont want to waste a lot of disk space.
It does sound a bit complicated, but it is just separation of concerns and breaking up the once monolithic docker binary into a client and a set of servers that all do smaller tasks and which can be restarted independently.