fd://是什么意思在dockerd -H fd://

Docker守护进程文档为大多数设置build议使用以下hosts选项:

 dockerd -H fd:// 

我猜fd代表文件描述符。 我不明白如何fd用于套接字通信。

我了解以下选项:

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

这些是unix域套接字和tcp套接字。 我知道如何使用这些套接字调用docker守护进程:

 docker -H tcp://0.0.0.0:2375 ps 

但是,如果我使用-H fd://启动docker守护进程,则以下调用会给出错误:

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

那么fd://的含义是什么? 有什么用吗?

当你启动Docker守护进程时, -H fd://会告诉Docker服务正在被Systemd启动,并将使用套接字激活。 然后systemd将创build目标套接字并将其传递给Docker守护进程使用。 这在Systemd 简介和套接字激活的介绍中有介绍 。 博客相当长,但真的值得一读,下面是对这个问题的理解的一个简短摘要:

  • Systemd是一个新的init系统,旨在取代传统的SysV init系统。 其关键特性之一是更快的init进程。
  • Socket activation是Systemd加速服务初始化中使用的技术之一
  • 要接收请求,服务需要一个套接字来侦听。 以Docker为例,它需要一个像/var/run/docker.sock或TCP套接字这样的unix domain socket套接字。 当然,这些套接字需要一些东西来创build它们,大部分时间是服务本身在开始的时候。
  • 通过套接字激活,SystemD将创build这些套接字并监听它们的服务,并在服务启动时将这些套接字传递给exec服务。 一个好处是,即使在相关服务启动之前,一旦套接字被成功创build,客户端请求就可以在套接字缓冲区中排队。
  • [docker.socket][3]使用的某个服务的套接字信息位于socket单元文件中,对于Docker,它是[docker.socket][3] ,内容为:

     [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 

让我们看看整个事情是如何工作的。 我有/etc/systemd/system下的docker.socketdocker.service文件。 ExecStart行是:

 ExecStart=/usr/bin/dockerd -H fd:// 
  1. 停止Docker服务: systemctl stop docker

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

    没有docker进程正在运行,也没有docker.sock

  2. 执行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 

    在启动docker.socket ,我们可以看到仍然没有docker进程在运行,但是/var/run/docker.sock套接字已经被创build,并且它属于进程systemd

    (Off-Topic:实际上socket已经准备好接收请求,即使docker.service还没有运行,systemd会在第一个请求到来的时候启动docker.service ,将已经创build的socket传递给Docker,这就是所谓的按需自动产卵)

  3. 启动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:// <....> 

    你可以告诉Docker正在运行。 让我们回过头来尝试从terminal手动执行/usr/bin/dockerd -H fd://手动:

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

    现在你看到了不同之处。 当你使用-H fd:// ,docker会期望socket的父进程被传递,而不是自己创build它。 当它由Systemd启动时,Systemd将完成这项工作,但是当您在terminal上手动启动它时,则不会执行该任务,因此docker守护程序进程失败并中止。 这是docker如何处理fd的代码://当docker守护进程启动时 ,如果你感兴趣,你可以看看。

另一方面,对于docker客户端,docker cli将从-H指定的hostparsingprotocol / addr,并向docker守护进程发出http请求。 默认主机是unix:///var/run/docker.sock 。 支持的协议包括tcpunixnpipefd 。 就我从源代码来看, fd的传输configuration和tcp是一样的,所以如果你有tcp socket监听,你可以用:

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

这是一样的:

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

在systemd中运行docker时使用-H fd://语法。 Systemd本身将在docker.socket单元文件中创build一个套接字并侦听它,并且该套接字通过docker.service单元文件中的fd://语法连接到docker守护进程。