In this tutorial we will learn how a pod is created from multiple containers and how they work together.
For Docker, the container is the smallest deployment unit. But other runtimes implement the concept of a pod which is a collection of one or more containers. Pods have a few special properties:
- All containers of a pod are scheduled on the same host
- All containers of a pod share the network namespace
This tutorial will demonstrate this by creating an isolated environment with a registry and Docker-in-Docker.
Launch the pod
The first container in the pod is created by launching a container mypod
with a long-running process. Usually this is an infinite loop but in our case, the primary container will run for one hour (3600 seconds):
docker container run -d --name mypod alpine sleep 3600
Launch registry
When launching the Docker registry as the first service, the new container will share the network namespace with te primary container called mypod
:
docker container run -d --name registry --network container:mypod registry
Launch Docker-in-Docker
The second container also shares the network namespace with the primary container mypod
- and at the same time with the Docker registry:
docker container run -d --name dind --privileged --network container:mypod docker:stable-dind \
dockerd --host=127.0.0.1:2375
Sidenote: The parameters dockerd --host=127.0.0.1:2375
force the Docker daemon to listen on port 2375 of localhost without using certificate authentication. This is for demonstration purposes only. In production environments, always use authenticated and encrypted network connections to your Docker daemon.
Launch work env
To start interacting with the isolated environment, we join another container to the pod. This one is based on the official Docker image:
docker container run -it --network container:mypod docker:stable sh
As the containers in the pod are only sharing the network namespace, the process list does not show the registry as well as the Docker daemon running in the pod:
ps
But when checking the listen ports, we can see the registry listening on port 5000 and the Docker daemon listening on port 2375:
netstat -tuna
To check the connection with the Docker daemon, we first need to configure the connection:
export DOCKER_HOST=tcp://127.0.0.1:2375
Then we can retrieve the version of client and server:
docker version
The commands above demonstrated that the processes running in the separate containers share a network namespace (see output of netstat
) but are unable to see each other in the process list (see output of ps
).
Use work env
As the final test, we can check if registry and Docker daemon are working correctly together.
Pull an image from Docker Hub:
docker image pull alpine
Apply a new tag for pushing to the local registry:
docker image tag alpine localhost:5000/alpine
Push the image to the local registry:
docker image push localhost:5000/alpine
Reset Docker daemon:
docker system prune --all --force
Pull the image from the local registry:
docker image pull localhost:5000/alpine
Quiz
What does a pod offer? Select all that apply
- Keeps the network layer isolated
- Composes containers to a single network environment
- Keeps process lists isolated
- Runs multiple processes in a single container
Which namespaces are shared in a pod? Select all that apply
- mount namespace
- uts
- network
- pid