When we move the app across environments like Developemnt, staging and production, we would have faced compatibility issues.
Containers solves this "dependency hell".
Virtual machines virtualizes on hardware level, which takes a dig at performance.
Docker uses LXC - linux containers, which sandboxes processes through namespaces.
LXC also provides cgroups - control groups, developed by google, for resources accounting and limiting.
Docker also uses CoW strategy, where all the containers share the same file system, the moment when a process in container wants to write to the file system, it makes a copy and writes on it.