Communicate with the Docker daemon from within a container
You have probably already run containers from the Docker Hub and noticed that some of them need to bind mount the /var/run/docker.sock
file. What is this file, and why it is sometimes used by containers? Short answer: it’s the Unix socket the Docker daemon listens on by default, and it can be used to communicate with the daemon from within a container.
Let’s consider Portainer, an open-source management interface used to manage a Docker host or a Swarm cluster. If used to manage the local Docker host Portainer can be ran with the following command, bind mounting the host’s Docker’s Unix socket.
$ docker container run -d \
-p 9000:9000 \
-v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
The interface is then available on port 9000 and allows you to manage containers, images, volumes, etc.
To do all those management actions, Portainer communicates with the local Docker daemon through the /var/run/docker.sock
file that it has access to via the bind mount.
Docker daemon API
When the Docker platform is installed on a host, the Docker daemon listens on the /var/run/docker.sock
Unix socket by default. This can be seen from the options provided to the daemon; it should contain the following entry:
-H unix:///var/run/docker.sock
Note: Additional -H options can be provided to the daemon so it also listens on tcp host/port or on other unix sockets.
All the HTTP endpoints defined in the Docker engine API v1.27 (last version to date), can thus be consumed through this unix socket.
Container Creation
Using the Portainer UI, we can easily run containers. Behind the hood, HTTP requests are sent to the Docker daemon through the docker.sock
. Let’s illustrate this and create a NGINX container using curl.
Note: When using the HTTP API, 2 steps are necessary to run a container: it needs to be created first and then it can be started.
Create a NGINX container
The following command uses curl to send the {“Image”:”nginx”}
payload to the /containers/create
endpoint of the Docker daemon through the unix socket. This will create a container based on NGINX and return its ID.
$ curl -XPOST --unix-socket /var/run/docker.sock -d '{"Image":"nginx"}' -H 'Content-Type: application/json' http://localhost/containers/create{"Id":"fcb65c6147efb862d5ea3a2ef20e793c52f0fafa3eb04e4292cb4784c5777d65","Warnings":null}
Start the container
Using the ID provided above, we can target the /containers/<ID>/start
endpoint to start the newly created container.
$ curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/fcb6...7d65/start
We can now verify the nginx container is up and running.
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fcb65c6147ef nginx “nginx -g ‘daemon …” 5 minutes ago Up 5 seconds 80/tcp, 443/tcp ecstatic_kirch
...
This illustrates how containers can easily be created behind the hood from within a container using the Docker socket. Obviously, a container will not be created using curl, but you get the idea.
Streaming events from the Docker daemon
The Docker API also exposes the /events
endpoint that can be used to get a stream of all the events the daemon generates. For instance, this can be used by a load balancer to get the creation or removal events of containers so it can dynamically update its configuration.
Let’s run a simple container and check how we can use Docker daemon events.
Running an Alpine container
The following command runs an Alpine container in interactive mode and bind mounts the docker.sock
.
$ docker run -v /var/run/docker.sock:/var/run/docker.sock -ti alpine sh
Listen events from the Docker daemon
From within the Alpine container, we first install the curl utility using the apk package manager.
# apk update && apk add curl
We can then send a HTTP request to the /events
endpoint through the Docker socket. The command hangs on, waiting for new events from the daemon. Each new event will then be streamed from the daemon.
$ curl --unix-socket /var/run/docker.sock http://localhost/events
Observe events
We then create a new container based on the NGINX image, and we watch, through the Alpine container standard output, the events generated by the Docker daemon.
$ docker container run -p 8080:80 -d nginx
We can observe that several events are received by the previous request.2
}
Basically, three events occurred:
- creation of the container
- connection to the default bridge network
- start of the container
Summary
I hope this quick explanation gives you a better understanding of the /var/run/docker.sock
file and how it can be used when bind mounted in a container. Obviously, applications using this socket will not use curl but will go for dedicated libraries to send HTTP requests to the daemon.
Note: Bind mounting the Docker daemon socket gives a lot of power to a container as it can control the daemon. It must be used with caution, and only with containers we can trust.
Đăng ký liền tay Nhận Ngay Bài Mới
Subscribe ngay
Cám ơn bạn đã đăng ký !
Lỗi đăng ký !
Add Comment