Containers are often described as lightweight virtual machines, which misses what they actually changed. Their significance is that they made an application's environment part of the artefact being deployed.
The problem was environment drift
Software depends on libraries, interpreters, configuration files and system settings. Any difference between a developer's machine and a server changes behaviour, sometimes subtly.
Servers also drift over time as packages are updated individually, so two machines built identically diverge within months. Reproducing a fault then becomes a matter of finding which one differs.
Configuration management tools attacked this by describing the desired state and converging machines toward it, which helped but still allowed accumulated differences to persist.
Shipping the dependencies changed the guarantee
A container image includes the application together with the libraries and files it needs, so the same image runs the same way wherever it is started.
The host provides only a kernel and isolation. Everything above that comes from the image, which removes the host's package state from the set of things that can differ.
That guarantee is what allows a build to be tested once and promoted through environments unchanged, rather than rebuilt for each one.
Isolation is not the same as virtualisation
Containers share the host kernel and are separated using process isolation features rather than emulated hardware. This is why they start in a fraction of a second.
The shared kernel is also the security caveat. A kernel vulnerability can affect every container on the host, which is why untrusted workloads are often given stronger isolation.
Immutability changed operations
Because images are fixed once built, updating an application means replacing containers rather than modifying them. Servers stop being long-lived things that are maintained.
This makes rollback straightforward, since the previous image still exists and starting it restores the previous behaviour exactly.
It also removes a whole category of incident caused by manual changes made on a server during an outage and then forgotten about.
The cost moved to orchestration
Once applications are packaged as disposable units, something must decide where they run, restart them when they fail and route traffic to them as they move.
That coordination layer is substantially more complex than the containers themselves, and it is where most of the operational learning curve now sits.
The trade was accepted because the alternative, machines that each accumulate their own history, produced failures that nobody could reproduce or reason about.