Click to share! ⬇️

Docker Bind Mounts

Let’s take a look at Bind Mounting in Docker and how persistent data works with those mounts. Bind Mounts are a little different than Docker Volumes, however the syntax to use them is quite similar. Bind Mounts are really cool since they allow local development with files on your host to update in real-time in a container. Technically, a Bind Mount is a mapping of the host files or directories into the container’s files or directories. So you can specify just a single file or an entire directory. In the background, it is like the location on the host and the location on the container is pointing to the same location on disk.


Bind Mount Example One

First, let’s create a directory on the host machine. We’ll name the directory host, then cd into that directory.

PS C:\code> mkdir host
PS C:\code> cd host
PS C:\code\host>

Ok, we have an empty directory of host that we are now working in. Now let’s run a container from the alpine image, and set up a bind mount between the host and container. The bind mount syntax is in blue and the ${pwd} to the left of : simply means, use the current working directory as the host directory. To the right of : is the directory in the container we are mapping to.

PS C:\code\host> docker container run -it --name alpine -v ${pwd}:/container alpine

Look at how the running container has a directory named container right away. When creating a bind mount in Docker, if you specify a directory in the container that is not already there, it is created for you.

/ # ls -l
total 56
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 bin
drwxrwxrwx    1 root     root          4096 Oct 23 16:24 container
drwxr-xr-x    5 root     root           360 Oct 23 16:29 dev
drwxr-xr-x    1 root     root          4096 Oct 23 16:29 etc
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 home
drwxr-xr-x    7 root     root          4096 Oct 21 09:23 lib
drwxr-xr-x    5 root     root          4096 Oct 21 09:23 media
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 mnt
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 opt
dr-xr-xr-x  176 root     root             0 Oct 23 16:29 proc
drwx------    1 root     root          4096 Oct 23 16:29 root
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 run
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 sbin
drwxr-xr-x    2 root     root          4096 Oct 21 09:23 srv
dr-xr-xr-x   11 root     root             0 Oct 23 16:29 sys
drwxrwxrwt    2 root     root          4096 Oct 21 09:23 tmp
drwxr-xr-x    7 root     root          4096 Oct 21 09:23 usr
drwxr-xr-x   12 root     root          4096 Oct 21 09:23 var

Change into the container directory and list out the files, we see there are none.

/ # cd container
/container # ls
/container #

Open a new instance of your terminal since the current instance is now connected to the running container. Navigate to the host directory that we created already. Note that it is empty.

PS C:\code\host> ls
PS C:\code\host>

Create a file on the host machine in the host directory and note that it now exists in that host directory.

PS C:\code\host> echo 'Created on host machine!' >> file1.txt
PS C:\code\host> ls


    Directory: C:\code\host


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       10/23/2020  12:37 PM             54 file1.txt

Navigate back to the original terminal that is still connected to the running container. List the files in that container directory.

/container # ls
file1.txt
/container # cat file1.txt
Created on host machine!

Whoa! The file exists in the container thanks to the bind mount we had set up. That is really cool. Now let’s create another file on the container and see what happens.

/container # echo 'File created on container!' > file2.txt
/container # ls
file1.txt  file2.txt

Navigate back to the terminal for working on the host where we can list out the files, and we can see that the file created on the container is now also present in the host.

PS C:\code\host> ls


    Directory: C:\code\host


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       10/23/2020  12:37 PM             54 file1.txt
-a----       10/23/2020  12:42 PM             27 file2.txt


PS C:\code\host> cat file2.txt
File created on container!

This is really interesting and you can start to see how this would be really beneficial to you when working with containers. You can really map anything you want from the host into the container. This concept is very helpful when you start talking about development on the host machine while running services on the container that are accessing files you may be editing on the host. As you make changes to files on the host, these are reflected in real-time within the container.


Bind Mount Example Two

The first example was as basic as we could possibly make it just to show the syntax of a bind mount and how it works. Let’s now look at an example that uses an Nginx web server in a container, that is able to serve HTML files you are editing on the local machine. Place this index.html file in the host directory like so:

index.html


<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <!-- Bootstrap CSS -->
    <link
      rel="stylesheet"
      href="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha2/css/bootstrap.min.css"
      integrity="sha384-DhY6onE6f3zzKbjUPRc2hOzGAdEf4/Dz+WJwBvEYL/lkkIsI3ihufq9hk9K4lVoK"
      crossorigin="anonymous"
    />

    <title>Hello, world!</title>
  </head>
  <body class="container mt-5">
    <div class="card">
      <div class="card-body">
        <h1 class="card-title">Hello World!</h1>
        <h3 class="card-subtitle mb-2 text-muted">Docker Bind Mounts</h3>
        <p class="card-text">
          Now we know how to use Docker Bind Mount with the Nginx web server.
        </p>
      </div>
    </div>

    <!-- Optional JavaScript; choose one of the two! -->

    <!-- Option 1: Bootstrap Bundle with Popper.js -->
    <script
      src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha2/js/bootstrap.bundle.min.js"
      integrity="sha384-BOsAfwzjNJHrJ8cZidOg56tcQWfp6y72vEJ8xQ9w6Quywb24iOsW913URv1IS4GD"
      crossorigin="anonymous"
    ></script>

    <!-- Option 2: Separate Popper.js and Bootstrap JS
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/5.0.0-alpha2/js/bootstrap.min.js" integrity="sha384-5h4UG+6GOuV9qXh6HqOLwZMY4mnLPraeTrjT5v07o347pj6IkfuoASuGBhfDsp3d" crossorigin="anonymous"></script>
    -->
  </body>
</html> 

Confirm we have a new file in our host directory.

PS C:\code\host> ls


    Directory: C:\code\host


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       10/23/2020   1:21 PM           1758 index.html

First, let’s just run an Nginx container with no bind mount and see what that gives us. We can name this container nginx1.

PS C:\code\host> docker container run -d --name nginx1 -p 80:80 nginx
c659e507bbc714ec3beb4e78acac2f232f9d9753614286dae143a0cc1b6a3817

Visiting the container in a browser shows us the Nginx splash screen. The container is not making any use of any files from the host machine.

docker bind mount example

Now let’s run a second container named nginx2 but this time we want to make use of a Bind Mount. Again the part of the command that specifies the bind mount is in blue.

docker> docker container run -d --name nginx2 -p 80:80 -v ${pwd}:/usr/share/nginx/html nginx
933bd7033cc370133f4b4e5475036610589e9424248d212d7d812f1c4ef7b852

We have two web servers running now. The first uses port 80 without a bind mount. The second uses port 8080 and is using a bind mount. We can see that the second web server is using the file from the localhost in the container. Very cool!

web server 1 and 2 in containers

The great thing about this is that changes on the host are reflected in real-time into the container. Let’s make a change to the source code of index.html. Note the highlighted line that is changed.


<div class="card">
    <div class="card-body">
    <h1 class="card-title">Have A Great Day!</h1>
    <h3 class="card-subtitle mb-2 text-muted">Docker Bind Mounts</h3>
    <p class="card-text">
        Now we know how to use Docker Bind Mount with the Nginx web server.
    </p>
    </div>
</div>

Reload the browser that is connected to the container, and voila, the updates happen right away.

docker bind mounts are great


More About Bind Mounts


Bind Mounts Summary

  • You Can Persist Data With Bind Mounts
  • Bind Mounts map a host file or directory to a container file or directory
  • This is like having two locations pointing to the same file(s)
  • Bind Mounds do not use UFS and host files overwrite any in container
  • You must define them during docker container run, can’t be used in a Dockerfile
  • run -v /Users/name/folder:/path/container (mac/linux)
  • run -v //c/Users/name/folder:/path/container(windows)
  • A Bind Mount allows you to attach an existing directory on your host to a directory inside of a container
  • You can use $(pwd) or ${pwd} when specifying a bind mount with the run command. This runs the shell command to print the current working directory so you don’t have to type out the entire directory path.
Click to share! ⬇️