Day 7 - Data Management and Volumes

 Till now we learned a lot about Docker images and Containers. In this session we will be learning about the data management and Volumes and its type as below.

Images are Read-Only and Containers are Read-Write.

Docker images are read-only templates that contain a set of instructions for creating containers that can run on the Docker platform.

A Docker image consists of read-only layers, each of which represents a Dockerfile instruction.

When you run a container from an image, Docker adds a writable layer on top of the read-only layers. This layer is where any changes made to the container, such as writing new files, modifying existing files, and deleting files, are stored. If you commit the container, the writable layer is converted into a new image layer that you can reuse and share.

By default, the data which is available in Container reside in Containers and not on Local Host where we are running our Docker Desktop.

Type of Data available in Containers.

Data storage in Docker is a topic that involves different options and considerations. According to the Docker documentation, by default all files created inside a container are stored on a writable container layer. This means that the data doesn't persist when the container no longer exists, and it can be difficult to get the data out of the container if another process needs it.

To overcome this limitation, Docker provides two options for containers to store files on the host machine, so that the files are persisted even after the container stops: volumes and bind mounts.

Volumes: Volumes are directories or files that exist on the host filesystem and are managed by Docker. They are isolated from the core functionality of the host machine and can be mounted into multiple containers simultaneously. These are mapped with inside of container Path to host filesystem. 

Bind mounts: Bind mounts are also directories or files that exist on the host filesystem, but they can be accessed and modified by non-Docker processes. They rely on the host machine's filesystem having a specific directory structure available and can pose security risks if used improperly.

If you're running Docker on Linux, you can also use tmpfs mounts to store files in the host system's memory only. These files are not persisted and are removed when the container stops.

We can divide data type in below Catgories for Containers.

1=> Images Data - Read Only data
2=> Temporary data - Data related to one time or recyclables data, which is not required to store.
3=> Permanent data - Data which need to be stored in database or File system to process further.

The Problem with data persistency in Container

Before proceeding let we test a case where we face problem with data persistency. This test case will be performing below actions.

=> It will be storing permanent data in state folder in Container itself
=> We will be testing if we can fetch data post Container stop/start
=> We will be testing if we can fetch data post Container Delete.

Download attached project and unzip in local drive and open the folder from File ==> Open Folder option in Visual Studio Code.


Let we Create Image for this project and then create container as below.

PS D:\Docker> docker build -t docker_v:1.0 .
 => => transferring context: 2B                                                                           0.0s 
 => [internal] load build definition from Dockerfile                                                      0.1s 
 => [internal] load build context                                                                         0.0s 
 => => transferring context: 1.32kB                                                                       0.0s 
 => CACHED [2/5] WORKDIR /app                                                                             0.0s 
 => CACHED [3/5] COPY package.json .                                                                      0.0s 
 => CACHED [4/5] RUN npm install                                                                          0.0s 
 => [5/5] COPY . .                                                                                        0.0s 
 => exporting to image                                                                                    0.1s 
 => => exporting layers                                                                                   0.1s 
 => => writing image sha256:8568df2a3580a6729f2cb732f53d63a838e0f4600fb889fe0ee74f2ba1063436      0.0s 
 => => naming to docker.io/library/docker_v:1.0                                                           0.0s 

PS D:\Docker> docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
docker_v     1.0       8568df2a3580   16 seconds ago   916MB
PS D:\Docker>
PS D:\Docker> docker run -p 3000:80 -d  --name docker_vol_container docker_v:1.0
e1024afaccfb555ea2b1cdea276b4ea865d9533e6be2ab599cf40ddd74b8e887
PS D:\Docker> 
Open Browser and enter the URL as below.

http://localhost:3000/

And Insert 3 Char (Max) State code and provide Code details as below. Click on SAVE 


As we discussed above this project will store information about stored data. Let we test the same as below.

=> Fetch Stored data 

To fetch stored data for that state you need to enter below URL and click on enter as below. For example, I am fetching information about MP state (in small letter).

http://localhost:3000/states/mp.txt


=> Data Persistency Problem.

As of now we stored data about MP states , now will be doing few tests for data persistence as below.

A=> Stop and Start Container: Let we restart container and check if data about MP state still available in Container.

PS D:\Docker> docker stop e1024afaccfb
e1024afaccfb
PS D:\Docker> docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                        PORTS    
 NAMES
e1024afaccfb   docker_v:1.0   "docker-entrypoint.s…"   15 minutes ago   Exited (137) 17 seconds ago
 docker_vol_container
PS D:\Docker> docker start e1024afaccfb
e1024afaccfb
PS D:\Docker>

As we can see data is still there persist in Container. 



B=> Delete and recreate New Container:  Let we recreate the container with same image and test if data persists,

PS D:\Docker> docker stop e1024afaccfb 
e1024afaccfb
PS D:\Docker> docker rm e1024afaccfb  
e1024afaccfb
PS D:\Docker> docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS D:\Docker>
PS D:\Docker> docker run -p 3000:80 -d  --name docker_vol_container docker_v:1.0
3d7c894ab534fac24164f9f53bbcaebb33d842f7158a0d312a04426ab1172dcc
PS D:\Docker>

As we can see data is NOT available now, and this is the problem which is resolved by Volumes.

Named Voulmes to rescue data post container recreation :

As we saw above post container recreation data is getting removed. To overcome this there is Name Volume feature in Docker. This type of Volume maps Container Folder to local host machine folder .
In our above test project Container folder is /app/states  and that will be mapped to local host machine as on_localhost_states as per below command.

PS D:\Docker> docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS D:\Docker>
PS D:\Docker> docker run -p 3000:80 -d --rm  --name docker_vol_container_v1.0 -v on_localhost_states:/app/states docker_v:1.0
d950cf70b901cd77fb2dc6b6bb5a53bf2dc28e8ae3ec6a4ef2a585bba2e0fbcd
PS D:\Docker>



Let we stop the container as post stopping this Container will be removed automatically as we used --rm option while creating the same.

Post that we will reuse above mentioned volume with new container as below.

And further we can check about Volumes using following command.
PS D:\Docker> docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                  NAMES
d950cf70b901   docker_v:1.0   "docker-entrypoint.s…"   7 minutes ago   Up 7 minutes   0.0.0.0:3000->80/tcp   docker_vol_container_v1.0
PS D:\Docker>
PS D:\Docker> docker stop d950cf70b901
d950cf70b901
PS D:\Docker> docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS D:\Docker>
PS D:\Docker> docker run -p 3000:80 -d --rm  --name docker_vol_container_v2.0 -v on_localhost_states:/app/states docker_v:1.0
47c2c6d4edc5dbd0ffe099862cca85d7291a5c8268f348ba5016e91076f5f73e
PS D:\Docker> 
PS D:\Docker> docker volume ls
DRIVER    VOLUME NAME
local         on_localhost_states
PS D:\Docker>
Let we test if data persist using below URL.

As we can see data now persist post Container recreation.





Using Bind Volume to Sync Data from Localhost to Container:

Suppose we need to change the Source Code for the project and wish to see reflected changes in our container, in this case we need to build the Image again as Images are READ-ONLY nature and any change to the source code to reflect at container level, this must be rebuilt.

To resolve such issue there is another type of Volume called: Bind Mount.

 Bind Volume Mount: A bind mount is a way to mount a file or directory on the host machine into a container. It is one of the types of mounts that Docker supports, along with volumes and tmpfs.

To use a bind mount, you need to specify the absolute path of the file or directory on the host machine, and the path where it is mounted in the container. You can use either the -v or --mount flag when running a container.

For example, if you want to bind mount the directory /home/user/data on the host machine to /data in the container, you can use either of these commands:

docker run -d -v /home/user/data:/data <image_name>
docker run -d --mount type=bind,source=/home/user/data,target=/data <image_name>

Usage: "Local Host machine Path": "Path in Container for project folder"

Bind mounts have some advantages compared to volumes, which are another way to persist data generated by and used by Docker containers. 

Volumes are completely managed by Docker, and do not depend on the host machine's directory structure.

Some of the advantages of bind mounts are:

•  They are very performant, since they use the host machine's filesystem directly.

•  They allow you to access files that already exist on the host machine, or share files between containers and the host.

•  They give you more control over the permissions and ownership of the files.


Let we test Both cases as below.

We will be testing both cases i.e changing Source code without and with Bind Mount as below.

Case -1: Changing Source Code without Bind Mount Volume.

PS D:\Docker> docker build -t docker_v:1.0 .
[+] Building 2.9s (10/10) FINISHED
 => [internal] load .dockerignore                                                                         0.0s 
 => => transferring context: 2B                                                                           0.0s 
 => [internal] load build definition from Dockerfile                                                      0.1s 
 => => transferring dockerfile: 151B                                                                      0.0s 
 => [internal] load metadata for docker.io/library/node:14                                                2.4s 
 => [1/5] FROM docker.io/library/node:14@sha256:a158d3b9b4e3fa813fa6c8c590b8f0a860e015ad4e59bbce5744d2f6  0.0s 
 => [internal] load build context                                                                         0.1s 
 => => transferring context: 2.47kB                                                                       0.0s 
 => CACHED [2/5] WORKDIR /app                                                                             0.0s 
 => CACHED [3/5] COPY package.json .                                                                      0.0s 
 => CACHED [4/5] RUN npm install                                                                          0.0s 
 => [5/5] COPY . .                                                                                        0.1s 
 => exporting to image                                                                                    0.1s 
 => => exporting layers                                                                                   0.1s 
 => => writing image sha256:da6d84a50326b428032bfef500791158a3a5f5baa4c6dec717cbbc8fb6b635e0              0.0s 
 => => naming to docker.io/library/docker_v:1.0                                                           0.0s 
PS D:\Docker>
PS D:\Docker>
PS D:\Docker> docker run -p 3000:80 -d --rm  --name docker_vol_container_v1.0 -v on_localhost_states:/app/states docker_v:1.0
c390d4ed47091171e0cf8ad5057d0118d305a096b7217614133613130a45edf8
PS D:\Docker> 
PS D:\Docker> docker ps -a 
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS
NAMES
c390d4ed4709   docker_v:1.0   "docker-entrypoint.s…"   14 seconds ago   Up 10 seconds   0.0.0.0:3000->80/tcp   
docker_vol_container_v1.0
PS D:\Docker> 



Now suppose we need to change in source code file like "states.html" file from "States and Union Territories of The India" TO "States and Union Territories of MY India"

Let we do the changes and see the impact.



Let we drop the container and recreated the same, but still the content not changed yet, this is because of Nature of Image, it's in READ ONLY mode.

To resolve this let we try with Bind Mount in next section.

PS D:\Docker> docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS                  NAMES
c390d4ed4709   docker_v:1.0   "docker-entrypoint.s…"   6 minutes ago   Up 6 minutes   0.0.0.0:3000->80/tcp   docker_vol_container_v1.0
PS D:\Docker> docker stop docker_vol_container_v1.0
docker_vol_container_v1.0

PS D:\Docker> docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS D:\Docker>
PS D:\Docker> docker run -p 3000:80 -d --rm  --name docker_vol_container_v1.0 -v on_localhost_states:/app/states docker_v:1.0
c0ebcffb4009cdceafcccd9a60972d4b344ded6074cc23e46a666e5cfd631f98
PS D:\Docker> 





Case -2: Changing Source Code with Bind Mount Volume.

Before proceeding to this test case let we firt understand below points.

1=> In this test case all Source codes are copied from Local to "/app" folder inside the Container, it is because of Dockerfile commands which is attached.

2=> File are stored are local directories on Local host and then they are getting compiled, and images got created post copied inside to Container.

3=> we will change "states.html" file at Local host level and that will get reflected inside the container at "/app/pages" folder.


PS D:\Docker> docker run -p 3000:80 -d --rm --name docker_vol_container_v2.0 -v "D:/Docker/pages/states.html:/app/pages/states.html" docker_v:1.0
099b0d2fe5ab795792775a73e8fb7e49e3a478aa67a6b7bb29444c3b303b462b
PS D:\Docker>

PS D:\Docker> docker ps -a 
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS
NAMES
099b0d2fe5ab   docker_v:1.0   "docker-entrypoint.s…"   23 seconds ago   Up 22 seconds   0.0.0.0:3000->80/tcp   
docker_vol_container_v2.0
PS D:\Docker>

Now let make changes in "states.html" file at local host and check the outcome.

Changes done on "states.html" file from "States and Union Territories of The India" TO "States and Union Territories of My India"




Just refresh the URL and Voila !!! changes are reflected now.

No comments:

Post a Comment

Total Pageviews