The docker daemon is a part of the docker engine. The docker engine is composed of other components such as the containerd and runc (will get to that later).
Docker client
The docker client is responsible for taking the user commands and converting them into the appropriate payload that will be sent over to the docker daemon. The default docker client that is being used is the binary /usr/bin/docker
that is added by default to the Linux machine when installing docker. This client is used in the shell as follows
docker pull ubuntu
Can we create our own Docker Client?
Yes, why not? But let's move to the next section where we discuss the Docker daemon. Then we can create a custom Docker client. 😃
Docker Deamon
Do you Remember the dockerd process that we saw previously when making pstree command?
This is the docker daemon process. It is the server side of the docker that is waiting to receive the user's commands. By default, the Docker daemon listens for connections on a Unix socket to accept requests from local clients. It can also be configured to listen on HTTP and receive requests from the network.
Listening to Unix sockets
We can find the socket file that is being used by docker to receive requests from local clients using the shell in /var/run/docker.sock
ubuntu@ip-172-31-31-29:~$ sudo ls -l /var/run/ | grep docker.sock
srw-rw---- 1 root docker 0 Sep 24 11:50 docker.sock
As you may already know unix socket is used for inter-process communication. This means that we can only send requests to the docker daemon from the same host. Let's not use the default docker executable and try curl.
curl --unix-socket /var/run/docker.sock http://localhost/images/json
[
{
"Containers": -1,
"Created": 1697049277,
"Id": "sha256:676aedd4776fe4617839f2517c46c44e8da9091d1c81a01f315101df51a2097f",
"Labels": null,
"ParentId": "",
"RepoDigests": [
"debian@sha256:7d3e8810c96a6a278c218eb8e7f01efaec9d65f50c54aae37421dc3cbeba6535"
],
"RepoTags": [
"debian:latest"
],
"SharedSize": -1,
"Size": 116549154,
"VirtualSize": 116549154
},
{
"Containers": -1,
"Created": 1695637028,
"Id": "sha256:3565a89d9e81a4cb4cb2b0d947c7c11227a3f358dc216d19fc54bfd77cd5b542",
"Labels": {
"org.opencontainers.image.ref.name": "ubuntu",
"org.opencontainers.image.version": "22.04"
},
"ParentId": "",
"RepoDigests": [
"ubuntu@sha256:9b8dec3bf938bc80fbe758d856e96fdfab5f56c39d44b0cff351e847bb1b01ea"
],
"RepoTags": [
"ubuntu:latest"
],
"SharedSize": -1,
"Size": 77823976,
"VirtualSize": 77823976
}
]
This is similar to docker images ls
command. It shows the docker images that exist on my machine.
Listening on HTTP
To configure remote access to the docker daemon, we need to make it accessible through the network. For that, we will make it listen on HTTP. For that, we will be making edits to the file /etc/docker/daemon.json
to make it listen to both the Unix socket and HTTP socket on port 2375
{
"hosts": ["unix:///var/run/docker.sock", "tcp://127.0.0.1:2375"]
}
Once we change the content of that file we need to restart the docker daemon process by
sudo systemctl restart docker.service
Then we can start sending HTTP requests to the daemon
ubuntu@ip-172-31-31-29:~$ curl -X GET http://localhost:2375/images/json
[{"Containers":-1,"Created":1697049277,"Id":"sha256:676aedd4776fe4617839f2517c46c44e8da9091d1c81a01f315101df51a2097f","Labels":null,"ParentId":"","RepoDigests":["debian@sha256:7d3e8810c96a6a278c218eb8e7f01efaec9d65f50c54aae37421dc3cbeba6535"],"RepoTags":["debian:latest"],"SharedSize":-1,"Size":116549154,"VirtualSize":116549154},{"Containers":-1,"Created":1695637028,"Id":"sha256:3565a89d9e81a4cb4cb2b0d947c7c11227a3f358dc216d19fc54bfd77cd5b542","Labels":{"org.opencontainers.image.ref.name":"ubuntu","org.opencontainers.image.version":"22.04"},"ParentId":"","RepoDigests":["ubuntu@sha256:9b8dec3bf938bc80fbe758d856e96fdfab5f56c39d44b0cff351e847bb1b01ea"],"RepoTags":["ubuntu:latest"],"SharedSize":-1,"Size":77823976,"VirtualSize":77823976},{"Containers":-1,"Created":1691124780,"Id":"sha256:01f29b872827fa6f9aed0ea0b2ede53aea4ad9d66c7920e81a8db6d1fd9ab7f9","Labels":{"org.opencontainers.image.ref.name":"ubuntu","org.opencontainers.image.version":"22.04"},"ParentId":"","RepoDigests":["ubuntu@sha256:ec050c32e4a6085b423d36ecd025c0d3ff00c38ab93a3d71a460ff1c44fa6d77"],"RepoTags":[],"SharedSize":-1,"Size":77823376,"VirtualSize":77823376}]
One of the Drawbacks of this approach is that docker will be accessible through the network which will introduce some security challenges. One approach to handle this is to use HTTPS, but it is still exposed 🥸