A container packages an application with its dependencies and runs it against the host kernel, which is why it starts far faster than a virtual machine, which has to boot an entire operating system with its own kernel first. That single difference is the reason containers became the default unit of deployment.
Most container problems are not really about Docker. They are about image size, layer caching, what happens to writes inside a container that gets recreated, and how a process behaves when it receives SIGTERM. The material below covers the mechanics first, because the debugging only makes sense once the model is clear.