Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what does fd:// mean exactly in dockerd -H fd://

Tags:

docker

sockets

Docker daemon documentation suggests the following hosts option for most setups:

dockerd -H fd:// 

I guess fd stands for file descriptor. I don't understand how fd is used for socket communication.

I understand the following options:

-H unix:///var/run/docker.sock -H tcp://192.168.59.106 -H tcp://10.10.10.2 

These are unix domain sockets and tcp sockets. I know how to call docker daemon using these sockets:

docker -H tcp://0.0.0.0:2375 ps 

But if I started docker daemon using -H fd://, the following call gives error:

$ docker -H fd:// ps error during connect: Get http:///v1.26/containers/json: http: no Host in request URL 

So what is the meaning of fd://? Is there any use for it?

like image 493
Mert Nuhoglu Avatar asked Apr 09 '17 05:04

Mert Nuhoglu


People also ask

What does allocate a pseudo tty mean?

The -t and -i flags allocate a pseudo-tty and keep stdin open even if not attached. This will allow you to use the container like a traditional VM as long as the bash prompt is running.

What happens when you press Cntrl p q inside the container?

You have to use two combinations, one after the other: ctrl+p followed by ctrl+q. You turn interactive mode to daemon mode, which keeps the container running but frees up your terminal. You can attach to it later using docker attach, if you need to interact with the container more.

How can I tell the difference between two docker images?

Use the container-diff command, followed by various flags, to define what types of differences you want to see between the images. This command displays how changes to a Dockerfile could affect the Docker container itself. The main flags are analyze and diff. The analyze flag is used against a single container.


2 Answers

When you start the Docker daemon, -H fd:// will tell Docker that the service is being started by Systemd and will use socket activation. systemd will then create the target socket and pass it to the Docker daemon to use. This is described in introduction to Systemd and in introduction to socket activation. The blogs are pretty long but really worth reading, here's a short summary of key points for understanding this question:

  • Systemd is a new init system intended to replace traditional SysV init system. One of its key features is faster init process.

  • Socket activation is one of the technologies used in Systemd to speed up service initialization

  • To receive requests, the service needs a socket to listen on. Take Docker as an example, it needs a unix domain socket like /var/run/docker.sock or a TCP socket. Of course these sockets needs something to create them and most of the time it is the service itself at start time.

  • With socket activation, SystemD will create these sockets and listen to them for services, and pass these sockets to service with exec when the service is started. One benefit is that client requests can be queued in the socket buffer once the socket is successfully created, even before the related service is started.

  • The socket info for a certain service used by Systemd is in socket unit file, for Docker it's [docker.socket][3] with content:

      [Unit]   Description=Docker Socket for the API   PartOf=docker.service    [Socket]   ListenStream=/var/run/docker.sock   SocketMode=0660   SocketUser=root   SocketGroup=docker    [Install]   WantedBy=sockets.target 

Let's see how the whole thing works. I have the files docker.socket and docker.service under /etc/systemd/system. The ExecStart line for docker.service is:

ExecStart=/usr/bin/dockerd -H fd:// 
  1. Stop Docker service: systemctl stop docker

    $> ps aux | grep 'docker' # the `grep` itself in the output is ignored $> lsof -Ua | grep 'docker' $>  

    No docker process is running, and no docker.sock

  2. Execute systemctl start docker.socket:

    $> systemctl start docker.socket $> ps aux | grep 'docker'  $> lsof -Ua | grep 'docker' systemd       1    root   27u  unix 0xffff880036da6000      0t0 140748188 /var/run/docker.sock 

    After start docker.socket, we can see that there's still no docker process running, but the socket /var/run/docker.sock has been created, and it belongs to the process systemd.

    (Off-Topic: Actually the socket is ready to receive requests now, even though docker is not running yet. systemd will start docker.service at the moment the first request comes, passing the already created sockets to Docker. This is so-called on-demand auto-spawning)

  3. Start docker.service

    $> systemctl start docker.service $> ps aux | grep 'docker' root     26302  0.0  1.8 431036 38712 ?        Ssl  14:57   0:00 /usr/bin/dockerd -H fd:// <....> 

    As you can tell Docker is now running. Let's go one step back and try to execute /usr/bin/dockerd -H fd:// manually from terminal:

    $> /usr/bin/dockerd -H fd:// FATA[0000] no sockets found via socket activation: make sure the service was started by systemd  

    Now you see the difference; when you use -H fd://, docker will expect the socket to be passed by its parent process rather than creating it by itself. When it's started by Systemd, Systemd will do the job, but when you manually start it on terminal, you don't do the job so the docker daemon process failed and aborted. This is the code of how docker process fd:// when docker daemon starts, you can have a look if you're interested.

On the other hand for the docker client, docker cli will parse protocol/addr from host specified in -H and make an http request to the docker daemon. The default host is unix:///var/run/docker.sock. The supported protocols include tcp, unix, npipe and fd. As far as I explore from source code the transport configuration for fd is the same with tcp so if you have tcp socket listening, you can just play it with:

$> docker -H fd://localhost:4322 ps CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES 

which is the same as:

docker -H tcp://localhost:4322 ps CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES 
like image 152
shizhz Avatar answered Oct 01 '22 00:10

shizhz


The -H fd:// syntax is used when running docker inside of systemd. Systemd itself will create a socket in the docker.socket unit file and listen to it, and this socket is connected to the docker daemon with the fd:// syntax in the docker.service unit file.

like image 31
BMitch Avatar answered Oct 01 '22 00:10

BMitch