DEV Community

Cover image for Learn Docker Volume and Bind Mounts using NGINX with Hands-on Sample
Ömer Berat Sezer
Ömer Berat Sezer

Posted on • Edited on

Learn Docker Volume and Bind Mounts using NGINX with Hands-on Sample

Docker volumes and bind mounts are crucial for managing persistent data in containers. Volumes, managed by Docker, are ideal for data storage across container lifecycles, offering better performance and flexibility. Bind mounts, directly linking host system directories to containers, provide more control and accessibility but are less portable.

volume

Docker Volume Use Cases

  • Data: Persist data beyond container restarts.
  • Shared Data Across Containers: Multiple containers accessing shared configuration or logs.
  • Backup & Restore: Easily back up and restore application data.
  • CI/CD Pipelines: Persist build artifacts across pipeline stages.

Bind Mount Use Cases

  • Local Development: Sync local files with a container for real-time code updates.
  • Accessing Host Logs: Containers writing logs directly to a host directory for easy monitoring.
  • Configuration Management: Using local config files (e.g., nginx.conf) inside containers.
  • Running Custom Scripts: Mounting scripts from the host to execute inside the container.

Two Hands-on below:

  • Hands-On #1: HTML page with Docker VOLUME
  • Hands-On #2: HTML page with Docker BIND MOUNTS

Hands-On #1: HTML page with Docker Volume

It shows:

  • how to create volume
  • how to create container, connection with volume and container file path
  • update the content of the index.html
  • create another container to verify persistency

GitHub Code Repo: https://github.com/omerbsezer/Fast-Docker/tree/main/hands-on-sample-projects/nginx-html-app

Steps:

  • Create Dockerfile:
FROM nginx:latest
# create a directory for your HTML page
RUN mkdir -p /usr/share/nginx/html
EXPOSE 80
Enter fullscreen mode Exit fullscreen mode
  • Build image:
user@docker:~$ docker build -t nginx-volume-demo .
Step 1/3 : FROM nginx:latest
latest: Pulling from library/nginx
fd674058ff8f: Pull complete
566e42bcee1c: Pull complete
2b99b9c5d9e5: Pull complete
bd98674871f5: Pull complete
1e109dd2a0d7: Pull complete
da8cc133ff82: Pull complete
c44f27309ea1: Pull complete
Digest: sha256:42e917aaa1b5bb40dd0f6f7f4f857490ac7747d7ef73b391c774a41a8b994f15
Status: Downloaded newer image for nginx:latest
 ---> f876bfc1cc63
Step 2/3 : RUN mkdir -p /usr/share/nginx/html
 ---> Running in 0725d56e04ba
 ---> Removed intermediate container 0725d56e04ba
 ---> 3468d5c325d6
Step 3/3 : EXPOSE 80
 ---> Running in ecc74ec0d4eb
 ---> Removed intermediate container ecc74ec0d4eb
 ---> 55f67ad03c41
Successfully built 55f67ad03c41
Successfully tagged nginx-volume-demo:latest
Enter fullscreen mode Exit fullscreen mode
  • Create new Docker volume object:
user@docker:~$ docker volume create nginx-volume
nginx-volume
Enter fullscreen mode Exit fullscreen mode
  • Run container in detach mode (-d:background run), connect volume and container file path:
user@docker:~$ docker run -d -p 8080:80 --name nginx-container -v nginx-volume:/usr/share/nginx/html nginx-volume-demo
292120421ac8049d5f858e9c410c959421b636e6a7bc9f4975a2bcdd81ef8b49
Enter fullscreen mode Exit fullscreen mode
  • Check the page with curl command:
user@docker:~$ curl http://localhost:8080

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
  • Enter the container, update index.html, exit from container:
user@docker:~$ docker exec -it nginx-container bash

root@292120421ac8:/# cd /usr/share/nginx/html

root@292120421ac8:/usr/share/nginx/html# apt-get update

root@292120421ac8:/usr/share/nginx/html# apt-get install vim nano -y
# update index.html with nano index.html like below

root@292120421ac8:/usr/share/nginx/html# cat index.html

<!DOCTYPE html>
<html>
<head>
<title>Docker Volume Demo</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Docker Volume Demo</h1>
<p>This page was updated inside the container using a DOCKER VOLUME!</p>
</body>
</html>

root@292120421ac8:/usr/share/nginx/html# exit
Enter fullscreen mode Exit fullscreen mode
  • Remove the running container:
user@docker:~$ docker container rm -f nginx-container
nginx-container

user@docker:~$ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
Enter fullscreen mode Exit fullscreen mode
  • Verify Persistency: Even if the container is removed, Docker volume in the local machine always save the data (make persistency). To prove it, another container (nginx-container-2) is created and curl again to see the updated info. In the second container, we can see the same data what we've updated on docker volume:
user@docker:~$ docker run -d -p 8080:80 --name nginx-container-2 -v nginx-volume:/usr/share/nginx/html nginx-volume-demo
41f461306aa3306dae24dbf8ee58b9d5e96e135e6cd56b11f6fd1b5c040792d3

user@docker:~$ curl http://localhost:8080

<!DOCTYPE html>
<html>
<head>
<title>Docker Volume Demo</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Docker Volume Demo</h1>
<p>This page was updated inside the container using a DOCKER VOLUME!</p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
  • Remove the container with ID:
user@docker:~$ docker ps -a
CONTAINER ID   IMAGE               COMMAND                  CREATED         STATUS         PORTS                                     NAMES
41f461306aa3   nginx-volume-demo   "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   nginx-container-2

user@docker:~$ docker rm -f 41f
41f

user@docker:~$ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
Enter fullscreen mode Exit fullscreen mode
  • Remove/clean up the Docker volume:
user@docker:~$ docker volume ls
DRIVER    VOLUME NAME
local     nginx-volume

user@docker:~$ docker volume rm nginx-volume
nginx-volume

user@docker:~$ docker volume ls
DRIVER    VOLUME NAME

Enter fullscreen mode Exit fullscreen mode

Hands-On #2: HTML page with Docker BIND MOUNTS

It shows:

  • how to create bind mounts
  • how to create container, sharing data between host and container
  • update the content of the index.html on host
  • show the update from container

GitHub Code Repo: https://github.com/omerbsezer/Fast-Docker/tree/main/hands-on-sample-projects/nginx-html-app

Steps:

  • Create Dockerfile:
FROM nginx:latest
# create a directory for your HTML page
RUN mkdir -p /usr/share/nginx/html
EXPOSE 80
Enter fullscreen mode Exit fullscreen mode
  • Create image:
user@docker:~$ docker build -t nginx-bind-mount-demo .

Step 1/3 : FROM nginx:latest
 ---> f876bfc1cc63
Step 2/3 : RUN mkdir -p /usr/share/nginx/html
 ---> Using cache
 ---> 3468d5c325d6
Step 3/3 : EXPOSE 80
 ---> Using cache
 ---> 55f67ad03c41
Successfully built 55f67ad03c41
Successfully tagged nginx-bind-mount-demo:latest
Enter fullscreen mode Exit fullscreen mode
  • Create directory and create index.html on HOST machine, before running nginx container:
user@docker:~$ mkdir nginx_bind_mount

user@docker:~$ ls
Dockerfile  nginx_bind_mount

user@docker:~$ cd nginx_bind_mount

user@docker:~$ touch index.html

user@docker:~$ nano index.html

# copy followings:
<!DOCTYPE html>
<html>
<head>
<title>Docker Bind Mounts Demo</title>
</head>
<body>
<h1>Docker Bind Mounts Demo</h1>
<p>This page was created in the HOST!</p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
  • Run container with bind mounts (-v /home/user/nginx_bind_mount:/usr/ share/nginx/html), files in the HOST is synchronized with the CONTAINER, we can see the data from host:
user@docker:~$ docker run -d -p 8080:80 --name nginx-container -v /home/user/nginx_bind_mount:/usr/
share/nginx/html nginx-bind-mount-demo

user@docker:~$ curl http://127.0.0.1:8080

<!DOCTYPE html>
<html>
<head>
<title>Docker Bind Mounts Demo</title>
</head>
<body>
<h1>Docker Bind Mounts Demo</h1>
<p>This page was created in the HOST!</p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
  • Then, update the file on the host /home/user/nginx_bind_mount/index.html with title, <title>Docker Bind Mounts Demo - update while running</title>, on the container, we can see the update immediately:
user@docker:~$ curl http://127.0.0.1:8080

<!DOCTYPE html>
<html>
<head>
<title>Docker Bind Mounts Demo - update while running</title>
</head>
<body>
<h1>Docker Bind Mounts Demo</h1>
<p>This page was created in the host!</p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Conclusion

This post shows how to create Docker Volume, Bind mounts with sample project.

If you found the tutorial interesting, I’d love to hear your thoughts in the blog post comments. Feel free to share your reactions or leave a comment. I truly value your input and engagement 😉

For other posts 👉 https://dev.to/omerberatsezer 🧐

Follow for Tips, Tutorials, Hands-On Labs for AWS, Kubernetes, Docker, Linux, DevOps, Machine Learning, Generative AI.

Top comments (0)