TL;DR: Writes go to a thin writable layer that belongs to the container and is deleted with it. A volume is storage managed outside that layer and outlives the container; a bind mount maps a host path in. Choose the storage backend for the required failure tolerance; a local volume alone does not protect against disk loss.
How to approach it
Explain the writable layer first, because it is the thing people do not know exists, and it makes the symptom obvious rather than surprising. Then separate volumes from bind mounts on ownership, and finish on the point that matters in production: a volume on one host is not durable storage.
A strong answer
An image is read-only layers. When a container starts, the runtime adds a writable layer on top, and every file the process creates or modifies lands there using copy-on-write. That layer belongs to the container. Remove the container and it is deleted, which is exactly the symptom in the question: a database wrote to its default directory, that directory was in the writable layer, the container was replaced on the next deploy, and the data went with it.
The writable layer is also slow for write-heavy work, because modifying a file that exists in a lower layer copies the whole file up first. Databases in particular should not be writing through it.
Volumes are storage the runtime manages, outside the union filesystem:
docker volume create pgdata
docker run -d --env-file ./postgres-demo.env -v pgdata:/var/lib/postgresql/data postgres:16
For this example, postgres-demo.env must supply the image's required initialization credentials and stay out of source control. Writes to /var/lib/postgresql/data bypass the writable layer entirely and go to the volume, which survives the container being removed and recreated. The runtime owns the location, so it is portable across hosts in the sense that the command works anywhere, though the data itself does not travel.
Bind mounts map a specific host path into the container:
docker run -v /home/vikas/app:/app node:20
You control the exact path, the container sees the host's files live, and edits on either side are immediately visible. That makes it the right tool for development, where you want to edit code without rebuilding. It is a poor tool for production, because it couples the container to a host's directory layout and to that host's file permissions, and UID mismatches between the host user and the container user produce permission errors that are tedious to unpick.
tmpfs mounts put a path in memory, which is useful for temporary data. Host swap settings and other copies of that data still matter before claiming it can never reach disk.
The production point worth making unprompted: a default local Docker volume relies on its host storage. A host failure can make it unavailable, and disk loss can destroy it; external volume drivers have different failure domains. It is persistence across container lifecycles, not durability: the failure domain is one machine, and a disk that dies takes the volume with it. Real durability means network storage, a managed database, or object storage, and in Kubernetes that distinction is the entire reason PersistentVolumes and StorageClasses exist: a PVC backed by network storage can be reattached to a pod on a different node, while an emptyDir lasts for the pod and survives an individual container restart.
Two things that follow from the same model. Logs should go to stdout rather than to a file, because the runtime collects stdout and a log file inside the container fills the writable layer and disappears with it. And a container should be treated as disposable: if losing it loses something you needed, that something belongs outside it.
Test the lifecycle you claim the data survives
For a disposable test database, write a record, stop and start the same Docker container, and read it again. Then remove the container and create a replacement attached to the same named volume. The first test checks a process/container restart; the second checks persistence across replacement. They are different events.
A third test restores a backup into a separate volume and starts the database against it. Use the database's supported backup method or a properly quiesced snapshot; copying an actively changing data directory with tar can produce an inconsistent backup. Verify the restored record and the recovery point before treating the backup as usable.
In Kubernetes, emptyDir survives individual container restarts within its pod but disappears with that pod. A PVC's durability depends on its storage backend and reclaim policy. Record what happens when the pod, node, claim or underlying disk is lost. “Persistent” without a named failure event is too vague to support a recovery promise.
What interviewers probe next
"What is the difference between VOLUME in a Dockerfile and -v at run time?" The instruction declares that a path should be a volume, and the runtime creates an anonymous one if you do not supply a name. Anonymous volumes accumulate invisibly, which is what docker volume prune is usually cleaning up.
"How do you back up a volume?" Use the application's supported consistent backup procedure, or quiesce it before copying files. Restore into separate storage and test recovery; a successful archive command alone does not establish database consistency.
"Two containers writing the same volume?" Possible and usually a mistake unless the software expects it. Most databases corrupt if two instances open the same data directory.
Common mistakes
Running a database with no volume, so the data is in the writable layer and the first redeploy loses it.
Using bind mounts in production, which ties the container to one host's paths and permissions.
Writing logs to a file inside the container, where they fill the writable layer and vanish with it.
Treating a volume as durable storage, when it is one disk on one machine.