We had vm-per-app before docker, so it was still build the image, test, and ship, but it actually had everything it needed inside the vm.

Docker helps with the portability due to it's ubiquitous it is now, but it's not like the vm requirement went away, the docker image still generally runs in a vm in any serious environment, and a lot more attention has to be paid to the vm:docker pairing than the previous hypervisor:vm pairing.