Docker Ep 17: Bind Mount — Instant code refresh from local

Amir Mustafa
6 min readJun 8, 2022

Bind mounts have been around since the early days of Docker.

Which Problem Bind Mount Fixes?

→ Whenever we build an image from Dockerfile, a snapshot of the code is kept in the Docker container. We can create containers and use our application.

→ Whenever we modify the code, it is not reflected in the application directly. We have to build the image again and create new containers.

→ Bind mount fixes this problem. Wouldn’t it be handy if we wrote code and instantly reflected it?

Introducing Bind Mounts

→ Bind mount help us fix different type of problems as seen above

→ Whenever we make any change in code it is not reflected in the code directly. We need to:

build the image → Create a container instance → Then code reflects

→ This happens because we only copy a snapshot of the code-base as a docker image

→ Therefore the subsequent change in the image will not be reflected, and therefore also not be there in the container.

→ During development, there should be a pretty way for which our code change is reflected in the container, without rebuilding the image or container.

→ Restarting every time will be a time-taking process. That’s where Bind mount comes into the picture.

→ Till now we have seen one type of Docker’s external storage:

Named Volumes: Fixes loss of file when a new container is created. Here we persist (i.e save) the data.

Bind mounts are somewhere similar to Docker Volumes with one difference:

Volumes — managed by docker. Code is kept somewhere in the host machine which we as a developer do not know

Bind Mount — managed by us. We define a path

→ The path that we will define now for Bind mount is readable + writable from the docker container.

→ Hence source code will have some connection bind mount path. Any change in code will be instantly reflected

Bind Mount Features: Persistent, Editable

Volumes: Persistent, Editing is not possible (as we do not know the path)

Implementing Bind Mount in Node.js Application:

→ Bind Mount cannot be set inside image i.e., not in Dockerfile.

→ It is set inside the container (like named volume).

STEP 1: Setting Docker Desktop Path to our Project or parent directory path for using Bind Mount.

A. For Linux and Mac machines:

i. Open Preference setting in Docker desktop:

ii. Click Resources → File Sharing:

B. Windows Machines: File sharing is auto on. We need not do this setting.

STEP 2: Check current volumes:

→ We can check docker volumes using the below commands:

docker volume ls

STEP 3: Implementing Bind Mount:

We need to write additional volume flag command like the below at the time of the container create command:

-v "<project-root-path>:/<docker-root-path>" // ADDITIONAL BindMount

→ The key idea is left side is the local code path and the right side is the docker path

docker run -d -p <webport>:<dockerport> --rm 
--name <container-name>
-v <named-volume-name>:<path-for-sharing>
-v "<project-root-path>:/<docker-root-path>" // BIND MOUNT
<image-name:tag>
eg.
docker run -d -p 3000:80 --rm --name feedback-app -v feedback-may28:/app/feedback -v "/Users/amirmustafa/Development/Projects/Docker-Node:/app" feedback-node:volumes

NOTE: We have place path in quotes because spaces and other character will also be accepted

To copy the local path we can easily copy from the Visual Studio Code path as shown below:

STEP 4: Once we have entered the below command with bind mount and ID is generated, open below URL:

http://localhost:3000

→ Nothing happens, an observation server crashes.

STEP 4: Observing Error in docker logs

docker logs <container-name or container-id>eg. docker logs feedback-app

Reason:

npm install was done by Dockerfile

When we write below the flag of a bind mount

local path (without node_modules) replaces docker path, hence the error.

-v "/Users/amirmustafa/Development/Projects/Docker-Node:/app" feedback-node:volumes

Solution:

→ We need to ignore node_modules at the time of bind mount creation

→ This can be done by adding Anonymous volumes with the path to file to ignore i.e adding an additional flag.

-v <file-to-ignore> <image-name:tag>
-v /app/node_modules feedback-node:volumes

Full command:

docker run -d -p 3000:80 --rm --name feedback-app -v feedback-may28-2022:/app/feedback -v "/Users/amirmustafa/Development/Projects/Docker-realtime-node/:/app" -v /app/node_modules feedback-node:volumes

TRICK:

Will add extra anonymous volume with node_modules path to ignore overwriting.

→ Let us re-run the below URL:

http://localhost:3000

→ Hurray our Node.js application runs

→ Let us now edit the code and refresh here.

→ Hurray, our latest code is rendered.

→ This is the solution that binds mount fixes.

→ Previously after code changes. We had to rebuild the image and create a container which was a time taking process.

→ Now we can get the latest code immediately in the browser.

Some Points:

→ Bind mount will never erase the local project codebase. Otherwise, it is data loss.

→  Local drive codebase overwrites in docker codebase and this is the reason we lost the npm install folder which we did from Dockerfile and fixed using Anonymous volume.

Video:

Closing Thoughts:

In this article, we understood the way to immediately render our code in the browser using Docker’s bind mount.

Thank you for reading till the end 🙌 . If you enjoyed this article or learned something new, support me by clicking the share button below to reach more people and/or give me a follow on Twitter and subscribe Happy Learnings !! to see some other tips, articles, and things I learn about and share there.

--

--

Amir Mustafa

JavaScript Specialist | Consultant | YouTuber 🎬. | AWS ☁️ | Docker 🐳 | Digital Nomad | Human. Connect with me on https://www.linkedin.com/in/amirmustafa1/