什么是fd://完全意味着在dockerd -H fd://

时间:2017-04-09 05:49:14

标签: sockets docker

Docker daemon documentation建议大多数设置使用以下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://的含义是什么?对它有用吗?

2 个答案:

答案 0 :(得分:32)

启动Docker守护程序时,-H fd://将告诉Docker该服务是由Systemd启动的,并将使用套接字激活。然后,systemd将创建目标套接字并将其传递给Docker守护程序以供使用。这在introduction to Systemdintroduction to socket activation中有所描述。博客很长,但真的值得一读,这里是理解这个问题的关键点的简短摘要:

  • Systemd是一个新的init系统,旨在取代传统的SysV init系统。其主要功能之一是更快的初始化过程。
  • Socket activation是Systemd中用于加速服务初始化的技术之一
  • 要接收请求,该服务需要一个套接字来监听。以Docker为例,它需要unix domain socket /var/run/docker.sock或TCP套接字。当然这些套接字需要一些东西来创建它们,并且大多数时候它是服务本身在开始时。
  • 通过套接字激活,SystemD将创建这些套接字并侦听它们以获取服务,并在服务启动时将这些套接字传递给exec服务。一个好处是,一旦套接字成功创建,即使在相关服务启动之前,客户端请求也可以在套接字缓冲区中排队。
  • Systemd使用的某个服务的套接字信息位于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
    

让我们看看整个事情是如何运作的。我在docker.socket下有docker.service/etc/systemd/system个文件。 ExecStart的{​​{1}}行是:

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

    systemctl stop docker

    没有正在运行的泊坞窗进程,也没有$> ps aux | grep 'docker' # the `grep` itself in the output is ignored $> lsof -Ua | grep 'docker' $>

  2. 执行docker.sock

    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,它属于进程/var/run/docker.sock

    (非主题:实际上套接字现在已准备好接收请求,即使systemd尚未运行.systemd将在第一个请求到来时启动docker,传递已创建的到Docker的套接字。这就是所谓的按需自动生成)

  3. 开始docker.service

    docker.service

    正如您所知,Docker现在正在运行。让我们退后一步,尝试从终端手动执行$> 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:// <....>

    /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 时,docker会期望套接字由其父进程传递,而不是自己创建它。当它由Systemd启动时,Systemd将完成这项工作,但是当您在终端上手动启动它时,您不会执行该任务,因此docker守护程序进程失败并中止。这是code of how docker process fd:// when docker daemon starts,你可以看看你是否感兴趣。

  4. 另一方面,对于docker客户端,docker cli将从-H fd://中指定的host解析protocol / addr,并向docker守护程序发出-H请求。默认主机为http。支持的协议包括unix:///var/run/docker.socktcpunixnpipe。据我从源代码中探讨,fd的传输配置与fd相同,所以如果你有tcp套接字监听,你可以用它来播放:

    tcp

    与:

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

答案 1 :(得分:2)

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