In this article, we will learn about the fundamentals of Docker volumes, Docker networking, and Docker compose. please check this link for your reference to get ideas on how to get started with Docker.
Docker Volumes:
Docker volumes are file systems that are mounted on Docker containers to persist data generated within containers over the lifecycle of containers.
By default when a container is stopped or deleted, that read-write layer is lost.
How to create docker volume?
By using the below command to create a docker volume.
$ docker volume create <volume name>
How to list volumes?
By using the below command we can list all created volumes in the host machine(virtual machine).
$ docker volume ls
How to inspect docker volumes?
- The inspect command will list the complete information of the container.
- Use the container ID listed in the first column with the inspect option.
$ docker volume inspect <volume name or volume ID>
How to delete docker volume?
By using the below command we can remove one or more volumes.
$ docker volume rm <volume name>
How to start a container with docker volume?
If the container started without docker volume once the container stopped or deleted the read-write layer is lost and the file does not exist.
$ docker run -v $(pwd):/path of the container -it --name <container name> <image name>
Docker Networking:
- Docker networking allows you to attach a container to as many networks as you like.
- You can also attach an already running container.
Docker Network Types:
- The most common network types being: bridge, overlay, and macvlan.
Bridge Networking:
The bridge network is the default network for new containers.
Bridge networking can be used in two different ways. The first is the default bridge network and the second is the user-defined bridge network.
Default Bridge Networking:
1. List current networks:
$ docker network ls
2. Start two alpine containers:
$ docker run -dit --name <container name> <image name>
3. Inspect the bridge network:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "6a719ea28c9e02d4d9efca2868c63796a4f0fce9e63340bc5d088509a298d98a",
"Created": "2022-09-06T06:04:12.966607493Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"0361fdedceaf55c9f94a10714b1175677878136d263d3c61eea7fc013a2a7784": {
"Name": "alpine2",
"EndpointID": "a0704b593b7aaa06179d1bff4a742cc8d07386ff4a6081fbeef3409a610908f1",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"7700982a608c8d522c0503e8b22a4a1b0e04fa7b88bec82bdefb3d8c439cad37": {
"Name": "alpine1",
"EndpointID": "c04377b8533de18db5e60b8f87b2aca4704f2b50513bdbed0be25853e67bd11d",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
4. Docker attach command:
The docker attach
command to connect to container (here we are connect to the alpine1).
Once we have attached to the container we can check the ip address of the container by using the command
ip addr show.
$ docker attach <container name>
/ # ip addr show
5. Verifying internet access within the container:
- We can access the internet by pinging google.com from within Alpine1. The command is limited to two ping attempts by the -c 2 parameter.
- Now try to ping the second container (alpine2). First, ping it by its IP address,
172.17.0.3
.
- It is successful. Ping the alpine2 container using its name after that. This won’t work.
- Use the detach shortcut CTRL + p CTRL + q to break free from alpine1 without pausing it (hold down CTRL and type p followed by q). Attach to alpine 2, then repeat steps 4, 5, and 6 there by using alpine1 instead of alpine2.
- Stop and remove both containers.
$ docker container stop <container name>
$ docker container rm <container name>
user-defined bridge networking:
- When you create Docker Containers using the default bridge network, accessing each other can only be done using IP addresses.
- But in case of user-defined bridge networks, you can access them by using both name and ip address.
1. Creating a own bridge network:
$ docker network create --driver bridge <desired network name>
2. Inspect the own bridge network:
$ docker network inspect <desired network name>
# docker network inspect my-alpine-bridge-net
[
{
"Name": "my-alpine-bridge-net",
"Id": "4b3f22d263c219ff8a60b18ab5f173653e9fce3324e5f2426f3a48acc3ae0a6e",
"Created": "2022-09-09T14:34:52.42820624Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
- The gateway for this network is 172.18.0.1, as opposed to 172.17.0.1 for the default bridge network. On your system, the exact IP address may differ.
3. Create four containers:
The –network flags should be noted. Docker run only allows you to connect to one network, thus you must use docker network connect thereafter to link alpine4 to the bridge network.
$ docker run -dit --name <container name> --network <desired network name> <image name>
We’re creating four containers. In this case, the alpine1, alpine2, and alpine4 containers connect the network in their own bridge network (my-alpine-bridge-net), while the alpine3 container connects to the default bridge network.
Check that all containers are running:
4. Inspect the bridge
network and the my-alpine-bridge-net
network:
$ docker network inspect <bridge name>
# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "6a719ea28c9e02d4d9efca2868c63796a4f0fce9e63340bc5d088509a298d98a",
"Created": "2022-09-06T06:04:12.966607493Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"21afd8b88b1abccc504a4c18588d3f3b096965c48f3dd8def1741b9b006775d9": {
"Name": "alpine3",
"EndpointID": "9e5027e1616d04871adb8b2c560f182047b7dba780e922c8880378d61fa21f27",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"3426a89348b1b53ff2a1ecdc9a67e96c4392372197bd752d6306c8212b195fad": {
"Name": "alpine4",
"EndpointID": "9b33f3b83c56486d0cc9d6eeff739c038fc0f589e1fc5b2f11754dde944aa5fd",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
$ docker network inspect <desired bridge name>
# docker network inspect my-alpine-bridge-net
[
{
"Name": "my-alpine-bridge-net",
"Id": "4b3f22d263c219ff8a60b18ab5f173653e9fce3324e5f2426f3a48acc3ae0a6e",
"Created": "2022-09-09T14:34:52.42820624Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"3426a89348b1b53ff2a1ecdc9a67e96c4392372197bd752d6306c8212b195fad": {
"Name": "alpine4",
"EndpointID": "ffb003695222056c9c20b0be11da619a904c8b5e7e9f9206bd918a2c7d5b111a",
"MacAddress": "02:42:ac:12:00:04",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": ""
},
"537ebec5ef83bd4dc5580cb84eb0cfc7d3817f3f828382d559c07be4aa52ce96": {
"Name": "alpine2",
"EndpointID": "b801d96529a4d5fb11937254eaf5a1f9ec669a1633ec25b15dec23d7a16980b5",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
},
"b3f011ed68cb182484bf1212be72cfae06e03f85041e8a289d936679c868cefc": {
"Name": "alpine1",
"EndpointID": "163b7ee5d73b00e990e311cb2af8993aee486becb21ffed02c9ab2a46ad60609",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
5. Pinging via alpine1:
The alpine1
container can be able to connect alpine2
, alpine4
and alpine1
(itself) by using the containers name as well as IP addresses.
You shouldn’t be able to connect to alpine3 from alpine1 at all because it is not a part of the own bridge network(my-alpine-bridge-net).
Also, you cannot access Alpine3 using Alpine1 IP address either. Find alpine3 IP address, 172.17.0.2, in the docker network inspect output for the bridge network and try pinging it.
Detach from alpine1 by pressing CTRL + p CTRL + q. (hold down CTRL and type p followed by q).
6. Pinging via alpine4:
The alpine4
is connected to both the default bridge
network and user defined network(my-alpine-bridge-net)
. It should be able to connect all of the other containers. But, you will need to address alpine3
by its IP address. Attach in alpine4 container and try to ping.
7. Pinging google.com:
Finally, we can test all four containers can connect to the internet by pinging google.com
.
Hold down CTRL and type p followed by q.
Hold down CTRL and type p followed by q.
8. Stop and remove all containers and the user defined(my-alpine-bridge-net) network.
Docker Compose:
Docker-compose utility helps to simplify the management of multiple containers, where one container might depend on another container’s availability.
For example, I will create two Docker containers using Docker compose. One docker container will have mysql database container and another Docker container have ngnix web server.
Let’s follow step by step.
1. Create Directory:
First create a webapp directory because we are creating web application and also index.html in this directory for testing purpose.
2.Create Dockerfile for Webapp:
Make a Dockerfile in the webapp directory to create a customised image for your application that includes the ngnix web server.
$ docker vi webapp/Dockerfile
After open the dockerfile write the code as mentioned below.
FROM ubuntu:16.04
RUN apt-get -y update && apt-get -y install nginx
COPY index.html /var/www/html/
WORKDIR /var/www/html
CMD ["/var/www/html/nginx", "-g", "daemon off;"]
EXPOSE 80
3. Create Docker Compose file:
Finally, in the current directory, create a docker compose(docker-compose.yml) file. This will define all of the containers that we are going to use in the current application.
$ vi docker-compose.yml
once you opened the yml file write the code as mentioned below.
version: '3'
services:
db:
image: mysql
container_name: mysql_db
restart: always
environment:
- MYSQL_ROOT_PASSWORD="secret"
web:
image: ngnix
build: ./webapp
depends_on:
- db
container_name: ngnix_web
restart: always
ports:
- "8080:80"
The above docker file have requirements for two containers.The first container contains MySQL database server, while the second contains web server.
4. Build Webapp Image:
Next build the webapp image by using the below mentioned command, it will create an image based on the Dockerfile and docker compose file.
$ docker-compose build
5. Launch Docker Containers:
Finally, use the docker-compose up command to start your containers. To run them in daemon mode, use the -d switch.
$ docker-compose up -d
6. Update Data in Web Application:
Let’s update your web application. I have added the following data to the webapp/index.html file.
$ echo "Welcome to Docker Compose" >> webapp/index.html
Use the commands below to recreate the webapp container and launch it again with docker-compose.
$ docker-compose build
$ docker-compose up -d
The output of the above command shown as below:
Access your web application on port 8080 of the docker host machine. The new data will be available here.