The term “operating system” has gotten a little overloaded.
Docker containers always run on a Linux kernel (except for the case of native Windows containers). On a non-Linux system (e.g., a Mac) there is a Linux virtual machine, and containers always run on that VM. All containers share that “host” or VM kernel (and by default are prohibited from making changes that would affect the whole system).
“Operating system” can also imply a stack of libraries, utilities, and programs that run on top of the kernel. Docker lets you run an Ubuntu userspace, or an Alpine userspace, or some other userspace...or no userspace at all. There can be minor incompatibilities between these (if you use a couple of specific things in GNU libc; if you believe /bin/sh is always GNU bash; ...).
You usually don’t want FROM scratch. You get nothing, beyond a couple of bits like /proc and /dev that Docker supplies for you. You do not get, for example, a shell. It’s most useful if you have a statically-linked Linux binary and for whatever reason want to wrap it in a container (your application generally must be written in C, C++, or Go, and you need to take special steps to statically link it).
Docker can never cause commands to get run on the host (especially if there’s a VM layer involved), and if your program’s primary goal is interacting with host programs or reading and writing host files then you actively don’t want the isolation that Docker provides. A different packaging system will probably work better for you.