One reason to use containers over VMs is that building, updating and extending containers is far easier and more maintainable than full virtual machines.
Containers give you the ability to layer the pieces you need on top of each other, so you are only responsible for the parts that you maintain. No need to rebuild an entire VM image every time one piece of the stack is updated.
Distribution of containers is also far more efficient than full virtual machines (especially important in a highly distributed environment).
I don't find the Docker API particularly intuitive. For my use-cases so far I've found it much simpler to spin up a VM if I want to duplicate a particular environment.
I think where Docker tends to shine is when you are operating at scale. For larger players using VMs to recreate a computing environment is expensive and eats into your bottom line. In such situations there's value in having some kind of tooling or API that partitions and simulates specific environments for processes running in the same kernel space. For better or for worse, in 2019, Docker is the best solution to this problem.
Containers give you the ability to layer the pieces you need on top of each other, so you are only responsible for the parts that you maintain. No need to rebuild an entire VM image every time one piece of the stack is updated.
Distribution of containers is also far more efficient than full virtual machines (especially important in a highly distributed environment).