Basics of Docker
Few Terminologies
Docker Engine
Docker Engine is a client-server application with these major components:
- A server which is a type of long-running program called a daemon process (the dockerd command).
- A REST API which specifies interfaces that programs can use to talk to the daemon and instruct it what to do.
- A command line interface (CLI) client (the docker command).
The CLI uses the Docker REST API to control or interact with the Docker daemon through scripting or direct CLI commands. Many other Docker applications use the underlying API and CLI.
The daemon creates and manages Docker objects, such as images, containers, networks, and volumes.
Docker daemon
The Docker daemon (dockerd) listens for Docker API requests and manages Docker objects such as images, containers, networks, and volumes. A daemon can also communicate with other daemons to manage Docker services.
Docker client
The Docker client (docker) is the primary way that many Docker users interact with Docker. When you use commands such as docker run, the client sends these commands to dockerd, which carries them out. The docker command uses the Docker API. The Docker client can communicate with more than one daemon.
Docker registries
A Docker registry stores Docker images. Docker Hub is a public registry that anyone can use, and Docker is configured to look for images on Docker Hub by default. You can even run your own private registry.
When you use the docker pull or docker run commands, the required images are pulled from your configured registry. When you use the docker push command, your image is pushed to your configured registry.
Images
An image is a read-only template with instructions for creating a Docker container. Often, an image is based on another image, with some additional customization. For example, you may build an image which is based on the ubuntu image, but installs the Apache web server and your application, as well as the configuration details needed to make your application run.
CONTAINERS
A container is a runnable instance of an image. You can create, start, stop, move, or delete a container using the Docker API or CLI. You can connect a container to one or more networks, attach storage to it, or even create a new image based on its current state.
By default, a container is relatively well isolated from other containers and its host machine. You can control how isolated a container’s network, storage, or other underlying subsystems are from other containers or from the host machine.
A container is defined by its image as well as any configuration options you provide to it when you create or start it. When a container is removed, any changes to its state that are not stored in persistent storage disappear.
Docker Architecture
Docker uses a client-server architecture. The Docker client talks to the Docker daemon, which does the heavy lifting of building, running, and distributing your Docker containers. The Docker client and daemon can run on the same system, or you can connect a Docker client to a remote Docker daemon. The Docker client and daemon communicate using a REST API, over UNIX sockets or a network interface.
First Docker Container
$ docker container run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:4cf9c47f86df71d48364001ede3a4fcd85ae80ce02ebad74156906caff5378bc
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
The steps are clearly shown on above output. First the docker daemon looked for the local image with name hello-world. If the image is not found locally, then it checked whether it is on default docker registry which is docker hub. As there was a image called hello-world on the docker hub, it pulled that image down, ran it on a container and exited.
Docker vs VM
Looking at above example, docker kind of looked like vm. But here are few differences.
- The VM is a hardware abstraction: it takes physical CPUs and RAM from a host, and divides and shares it across several smaller virtual machines. There is an OS and application running inside the VM, but the virtualization software usually has no real knowledge of that.
- A container is an application abstraction: the focus is really on the OS and the application, and not so much the hardware abstraction. Many customers actually use both VMs and containers today in their environments and, in fact, may run containers inside of VMs.
Docker images
Fetching docker image from the registry
$ docker image pull alpine
Using default tag: latest
latest: Pulling from library/alpine
df20fa9351a1: Pull complete
Digest: sha256:185518070891758909c9f839cf4ca393ee977ac378609f700f60a771a2dfe321
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
This command will look at the default docker registry ie dockerhub (can be changed) for image called alpine and if found, it will download the image on our local box. Now with this image, we can create multiple containers which are like the multiple instances of this image.
Alpine Linux is a Linux distribution based on musl and BusyBox, designed for security, simplicity, and resource efficiency.
Listing the images on our box
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest a24bb4013296 3 months ago 5.57MB
hello-world latest bf756fb1ae65 8 months ago 13.3kB
We have two images on the box, one being hello-world which we fetched earlier and other one is alpine.
Running container based on the image
$ docker container run alpine ls -la
total 8
drwxr-xr-x 1 root root 6 Sep 24 06:19 .
drwxr-xr-x 1 root root 6 Sep 24 06:19 ..
-rwxr-xr-x 1 root root 0 Sep 24 06:19 .dockerenv
drwxr-xr-x 2 root root 4096 May 29 14:20 bin
drwxr-xr-x 5 root root 340 Sep 24 06:19 dev
drwxr-xr-x 1 root root 66 Sep 24 06:19 etc
drwxr-xr-x 2 root root 6 May 29 14:20 home
drwxr-xr-x 7 root root 223 May 29 14:20 lib
drwxr-xr-x 5 root root 44 May 29 14:20 media
drwxr-xr-x 2 root root 6 May 29 14:20 mnt
drwxr-xr-x 2 root root 6 May 29 14:20 opt
dr-xr-xr-x 768 root root 0 Sep 24 06:19 proc
drwx------ 2 root root 6 May 29 14:20 root
drwxr-xr-x 2 root root 6 May 29 14:20 run
drwxr-xr-x 2 root root 4096 May 29 14:20 sbin
drwxr-xr-x 2 root root 6 May 29 14:20 srv
dr-xr-xr-x 13 root root 0 Aug 21 07:57 sys
drwxrwxrwt 2 root root 6 May 29 14:20 tmp
drwxr-xr-x 7 root root 66 May 29 14:20 usr
drwxr-xr-x 12 root root 137 May 29 14:20 var
What happened in the background when we ran the command is that the docker client requested docker daemon to search for image called alpine and when the daemon found the image name called alpine then it created a brand new container and ran the command inside the container. Then container shut down.
Now if we were to run the same command again, the container that will be created this time will be a brand new container. I will demonstrate this in a second.
Creating new container executing /bin/sh
$ docker container run alpine /bin/sh
Command executed successfully but nothing happened. WHY? It is because the command executed successfully and the container shut itself down. To tell the docker that we need a interactive session we use following commands.
$ docker container run -it alpine /bin/sh
/ # ls -la
total 8
drwxr-xr-x 1 root root 18 Sep 24 07:00 .
drwxr-xr-x 1 root root 18 Sep 24 07:00 ..
-rwxr-xr-x 1 root root 0 Sep 24 07:00 .dockerenv
drwxr-xr-x 2 root root 4096 May 29 14:20 bin
drwxr-xr-x 5 root root 360 Sep 24 07:00 dev
drwxr-xr-x 1 root root 66 Sep 24 07:00 etc
drwxr-xr-x 2 root root 6 May 29 14:20 home
drwxr-xr-x 7 root root 223 May 29 14:20 lib
drwxr-xr-x 5 root root 44 May 29 14:20 media
drwxr-xr-x 2 root root 6 May 29 14:20 mnt
drwxr-xr-x 2 root root 6 May 29 14:20 opt
dr-xr-xr-x 910 root root 0 Sep 24 07:00 proc
drwx------ 1 root root 26 Sep 24 07:00 root
drwxr-xr-x 2 root root 6 May 29 14:20 run
drwxr-xr-x 2 root root 4096 May 29 14:20 sbin
drwxr-xr-x 2 root root 6 May 29 14:20 srv
dr-xr-xr-x 13 root root 0 Aug 21 07:57 sys
drwxrwxrwt 2 root root 6 May 29 14:20 tmp
drwxr-xr-x 7 root root 66 May 29 14:20 usr
drwxr-xr-x 12 root root 137 May 29 14:20 var
/ # exit
This time the container didnot shut down but instead gave us a shell to work with.Now on this shell inside of our newly created container we can execute shell commands.
Listing the containers
Active Containers
To list the currently active container we can use following command.
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Looks like there is no any results. It is because we do not have any active running containers.
All Containers
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
21bcebe696a3 alpine "/bin/sh" 6 minutes ago Exited (0) 3 minutes ago strange_bouman
6684f8bd6f73 alpine "/bin/sh" 8 minutes ago Exited (0) 8 minutes ago brave_wescoff
d5d18e291759 alpine "ls -la" 47 minutes ago Exited (0) 47 minutes ago funny_blackburn
32045da0a193 hello-world "/hello" 50 minutes ago Exited (0) 50 minutes ago recursing_chaum
These are the list of containers that were created. And we can see from the status that they exited some N minutes ago. One interesting thing here is notice the CONTAINER ID of each of the container created, they all are different which means all the containers we have created are indeed different from each other even though they are created from same image.
Reference
https://training.play-with-docker.com/ops-s1-hello/
https://docs.docker.com/get-started/overview/