Difference between bind mount and bind volume

I’m trying to understand the difference between these 2 commands

docker volume create --driver local \
--opt type=none \
--opt device=$(pwd)/config\
--opt o=bind \
config_vol

docker run -it --volume config_vol:/app/config

and simply

docker run -it --volume $(pwd)/config:/app/config

I understand that a volume is a stateful entity, but what confuses me is that if my config folder is empty initially when running the docker with a pre-created volume, it copies the contents of the container into the config folder which is desired behavior, but the second command hides the contents of the container and treats it as an empty folder in the container.

That is, after running the docker containers, in the first situation if I ran ls /app/config in the interactive terminal, I’d see config.json in the output, but in the second situation I’d see nothing.

Why is that?

The second command mounts a directory on your host (in your case, $pwd/config) onto the container path /app/config. Your volume is not used at all.

The --volume option can be written as <volumename>:<container path name>, in which case it mounts the named volume onto the container. The copy behaviour you described happens in this scenario, if the the volume is empty.

The --volume option can also be written as <host path name>:<container path name>. This is a bind mount, and does not use volumes at all. The copy behaviour does not apply here.

Your first docker run command was a volume mount. The second was a bind mount.