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

Mer*_*glu 24 sockets docker

Docker守护程序文档hosts为大多数设置建议以下选项:

dockerd -H fd://
Run Code Online (Sandbox Code Playgroud)

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

我理解以下选项:

-H unix:///var/run/docker.sock -H tcp://192.168.59.106 -H tcp://10.10.10.2
Run Code Online (Sandbox Code Playgroud)

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

docker -H tcp://0.0.0.0:2375 ps
Run Code Online (Sandbox Code Playgroud)

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

$ docker -H fd:// ps
error during connect: Get http:///v1.26/containers/json: http: no Host in request URL
Run Code Online (Sandbox Code Playgroud)

那么这是什么意思fd://?它有用吗?

shi*_*zhz 37

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

  • 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
    
    Run Code Online (Sandbox Code Playgroud)

让我们看看整个事情是如何运作的.我有文件docker.socketdocker.service/etc/systemd/system.该ExecStartdocker.service是:

ExecStart=/usr/bin/dockerd -H fd://
Run Code Online (Sandbox Code Playgroud)
  1. 停止Docker服务: systemctl stop docker

    $> ps aux | grep 'docker' # the `grep` itself in the output is ignored
    $> lsof -Ua | grep 'docker'
    $> 
    
    Run Code Online (Sandbox Code Playgroud)

    没有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
    
    Run Code Online (Sandbox Code Playgroud)

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

    (Off-Topic:实际上套接字已经准备好接收请求了,即使docker它还没有运行.systemd将docker.service在第一个请求到来时启动,将已经创建的套接字传递给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://
    <....>
    
    Run Code Online (Sandbox Code Playgroud)

    你可以告诉Docker现在正在运行.让我们退后一步,尝试/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 
    
    Run Code Online (Sandbox Code Playgroud)

    现在你看到了差异; 当你使用时-H fd://,docker会期望套接字由其父进程传递,而不是自己创建它.当它由Systemd启动时,Systemd将完成这项工作,但是当您在终端上手动启动它时,您不会执行该任务,因此docker守护程序进程失败并中止.这是docker进程fd代码://当docker守护进程启动时,你可以查看一下你是否感兴趣.

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

$> docker -H fd://localhost:4322 ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
Run Code Online (Sandbox Code Playgroud)

这与:

docker -H tcp://localhost:4322 ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
Run Code Online (Sandbox Code Playgroud)

  • 很棒的描述@shizhz (2认同)

BMi*_*tch 5

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