Docker Basics day 3
Welcome to the third article of Docker Basics. Previously, we learned some important concepts of Docker and also basic commands. Now let's study how to use Networks and Storage.?I'm assuming you have a fair bit of idea about what Docker consists of and at least know how to download an image and run a container. If you don't, kindly read the past two articles:
Storage in Docker
Storage in Docker can persist data or files from the host system into our containers and vice-versa. To accomplish this, we can either use Bind Mounts or Volumes.?
Bind Mounts: are used to storing files and directories into the container. Most of the time, you will use them for project files.?
Volumes: are used to persist data. You will use them for databases.?
Using bind mounts with an Nginx container
We learned how to run an Nginx container using the command:
$ docker container run --rm -p 80:80 --name myNginx nginx
To run our content in this Nginx server. To fulfil this, as the first step, we need to prepare the assets in our host system that we want the container to load. Save your index.html and styles.css on a local directory.?
Now, let's put it in the Nginx container. To do this, we need to run the same command we used before, but with a -v argument to mount the directory.?
$ docker container run --rm -p 80:80 --name myNginx -v $(pwd)/html:/usr/share/nginx/html nginx
Note: 2nd part is the part of the same command
Now, you will be able to see your index.html on the Nginx server, rather than the boring default page.
Using Volumes with a Mongo image
As I explained before, one of the characteristics of Docker containers is its “destroyable” nature, which means, we can delete any containers quickly without leaving any tracks behind, this is useful for many situations, but?how does this play when we need to persist some data??Does it mean once we remove a DB container, all our data will be gone forever??We don’t want that for sure.
Fortunately for us, the Docker team thought of a solution for this called “Volumes”. In a general way, Volumes are specific units of storage managed by the Docker engine, which we can use to persist any required data. Most of the database images out there already have volumes configured by default. However, here we will learn to create our custom volumes and use them in our DB containers.
Now, let's run a mango container
$ docker container run -d --name myMongo mongo
This image was assigned by two volumes by default. We can check by inspecting it:
$ docker container inspect myMongo
large JSON output where the only part we care about is this one:
..
"Mounts": [
{
"Type": "volume",
"Name": "e0d5c4ad6b9d354518af3fc8b7e2acbfaad05661ba380471f87a7be570faafa0",
"Source": "/var/lib/docker/volumes/e0d5c4ad6b9d354518af3fc8b7e2acbfaad05661ba380471f87a7be570faafa0/_data",
"Destination": "/data/configdb",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "b919181b745c0547cda1ea73b2ab1a4b3fe942e13eab9d08c03a38a0cd37d84b",
"Source": "/var/lib/docker/volumes/b919181b745c0547cda1ea73b2ab1a4b3fe942e13eab9d08c03a38a0cd37d84b/_data",
"Destination": "/data/db",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
....
We can see this container uses two volumes. One for configuration values and the other one for data. Notice how the names are unique identifiers that represent the volumes created once the container starts. You can list these volumes by entering the following command:
$docker volume ls
Notice how the volume names match the ones from your docker inspect print. These volumes will be available even though the linked container stops. So any persisted data here will be safe. Let’s test this by adding a record to our mongo database. First, run this command to get access to the mongo shell:
$ docker container exec -it myMongo mongo
And add a record by simply entering this mongo instruction:
> db.getCollection('my_collection').insert({message:'Hello Docker'})
Using the default volumes has its caveats.?What would happen if we delete the containers used by those volumes??The volumes will still be there, but if we start new DB containers, these are going to use new volumes instead of the old ones. There’s a way to link the first volumes with the new containers, but since the early volumes are labelled using long unique identifiers, the process may end up being quite cumbersome. Also, you might have a lot of volumes used by different containers.?How could you possibly identify which volume you need among those other ones??Hard task.
To create a volume, you only have to run this command:
$docker volume create my-mongo-volume
Now let’s create a new instance of mongo — so that we don’t have to delete the old one — but this time, we will be linking the new volume created:
$ docker container run -d -v my-mongo-volume:/data/db --name myNewMongo mongo
As you can see, this time we include a “-v” option, this is something quite familiar with what we did in the past section. The only difference is that we are using the volume’s name that we created before. The part after the colon represents the destination path of the container — where the volume will be mounted. In this case, we want to mount a volume to persist our data, so we use the?/data/DB?path. After using the past command, we will have a running container linked to our recently created volume. Any data we persist here will be safe, no matter what we do with the container running, and as long we don’t delete the volume linked. We can link this same volume to other containers to test different configurations. You can also link volumes to different versions of the same image as well, as long as there are no breaking changes of course.
Inspect the “myNewMongo” container. You should see changes on the “Mounts” section:
$docker inspect myNewMong
...
"Mounts": [
...
{
"Type": "volume",
"Name": "my-mongo-volume",
"Source": "/var/lib/docker/volumes/my-mongo-volume/_data",
"Destination": "/data/db",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
...
Now instead of a unique identifier as “Name”, we have the name of the created volume.