如何通过 TCP 公开 docker API?

如何通过 TCP 公开 docker API?

我正在使用 portainer,但无法管理远程端点。我尝试使用命令行连接到远程 docker 节点,但收到一条消息Cannot connect to the Docker daemon at tcp://<remote_ip>:<port>. Is the docker daemon running?

是的,它们正在运行。我已将自己添加到 docker 组,并且可以通过 SSH 进入节点来访问 docker。但是我无法远程访问任何 docker 节点。

我修改了/etc/default添加/取消注释DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4 -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"

我还修改了/etc/init.d/docker/etc/init/docker.conf以包括DOCKER_OPTS="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"

我重启了docker服务,过程中多次退出登录,还是连接不上远程节点,甚至连通过IP连接本地节点都连接不上。

我遗漏了什么?哪个文件中的哪个配置通过 TCP 公开了 API?

user@hostname:~$ docker -H tcp://<REMOTE_IP>:2375 info
Cannot connect to the Docker daemon at tcp://<REMOTE_IP>:2375. Is the docker daemon running?
user@hostname:~$ docker -H tcp://127.0.0.1:2375 info
Cannot connect to the Docker daemon at tcp://127.0.0.1:2375. Is the docker daemon running?
user@hostname:~$ docker -H tcp://<LOCAL_IP>:2375 info
Cannot connect to the Docker daemon at tcp://<LOCAL_IP>:2375. Is the docker daemon running?
user@hostname:~$

编辑: 运行ps aux | grep -i docker将返回此 -

root      3581  0.1  0.2 596800 41540 ?        Ssl  04:17   0:35 /usr/bin/dockerd -H fd://
root      3588  0.0  0.0 653576 14492 ?        Ssl  04:17   0:18 docker-containerd -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc

答案1

我找到了解决方案,感谢Ivan Krizsan 的帖子

我必须/lib/systemd/system/docker.service在我的 Ubuntu 16.04.2 LTS 系统上进行编辑来修改该行

ExecStart=/usr/bin/docker daemon -H fd:// -H tcp://0.0.0.0:

然后

sudo systemctl daemon-reload
sudo systemctl restart docker.service

一切正常 :-)。下一步是弄清楚如何保护 docker 守护进程不被劫持。

答案2

/etc/default 目录是发行版维护者放置其配置文件的地方。如果您直接从 Docker 的存储库安装 Docker,则不会使用此目录。

/lib/systemd目录是软件包安装其 systemd 文件的位置,它们将在升级时覆盖那里的任何更改。如果您使用此目录,您的更改将会丢失。

要对持久的 systemd 单元文件进行自己的更改,您可以在 中创建一个单元文件/etc/systemd/system/docker.service.d/,例如这是我的标准/etc/systemd/system/docker.service.d/override.conf

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd

该覆盖只是从 systemd 取消设置 dockerd 守护进程的所有命令行标志。完成后,您可以覆盖/etc/docker/daemon.jsondocker 使用的每个设置,并且根据设置,无需重新启动守护进程即可重新加载。例如,这里有一个示例 /etc/docker/daemon.json:

{
"debug": false,
"experimental": true,
"hosts": ["fd://", "tcp://0.0.0.0:2376"],
"labels": ["foo=bar", "fez=baz"],
"log-driver": "json-file",
"log-opts": {"max-size": "10m", "max-file": "3"},
"storage-driver": "overlay2",
"tlscacert": "/etc/docker/certs/ca.pem",
"tlscert": "/etc/docker/certs/host-cert.pem",
"tlskey": "/etc/docker/certs/host-key.pem",
"tlsverify": true
}

为了您的目的,您只需要其中的一行来设置主机。

上述配置文件中一个极其重要的部分是 TLS 设置。如果您未在客户端和服务器之间配置相互 TLS,并且打开 docker 来监听网络,则您运行的相当于一个开放的 telnet 服务器,允许 root 用户无需密码即可登录。如果您更喜欢 ssh 而不是 telnet,或者如果您更喜欢为 root 帐户设置密码,那么您必须配置 TLS。互联网上经常会扫描 docker API 端口,如果你跳过这个配置步骤,很快就会发现你的主机上安装了恶意软件。

有关如何为客户端和服务器配置 TLS 密钥的完整详细信息,请参见: https://docs.docker.com/engine/security/https/


请注意,如果客户端(运行命令的客户端和远程节点)上的 docker 版本为 18.09 及以上,则可以使用 ssh 而不是配置 TLS。这需要使用 值DOCKER_HOSTssh://user@host例如

docker -H ssh://user@host container ls

答案3

有一个官方文档描述了如何配置 Docker 守护进程监听连接的位置

systemd 与 daemon.json

将 Docker 配置为使用 systemd 单元文件和 daemon.json 文件监听连接会导致冲突,从而阻止 Docker 启动。

使用 systemd 单元文件配置远程访问

  1. 使用命令 sudo systemctl edit docker.service 在文本编辑器中打开 docker.service 的覆盖文件。

  2. 添加或修改以下行,替换您自己的值。

    [Service]
    ExecStart=
    ExecStart=/usr/bin/dockerd -H fd:// -H tcp://127.0.0.1:2375
    
  3. 保存文件。

  4. 重新加载 systemctl 配置。

    $ sudo systemctl daemon-reload
    
  5. 重新启动 Docker。

    $ sudo systemctl restart docker.service
    
  6. 通过检查 netstat 的输出来确认 dockerd 是否正在监听配置的端口,以查看更改是否得到遵守。

    $ sudo netstat -lntp | grep dockerd
    tcp        0      0 127.0.0.1:2375          0.0.0.0:*               LISTEN      3758/dockerd
    

配置远程访问daemon.json

  1. 设置 /etc/docker/daemon.json 中的 hosts 数组以连接到 UNIX 套接字和 IP 地址,如下所示:

    {
    "hosts": ["unix:///var/run/docker.sock", "tcp://127.0.0.1:2375"]
    }
    

    将 Docker 配置为使用 systemd 单元文件和 daemon.json 文件监听连接会导致冲突,从而阻止 Docker 启动。

    1. 添加或修改以下行,替换您自己的值。

      [Service]
      ExecStart=
      ExecStart=/usr/bin/dockerd
      
    2. 保存文件。

    3. 重新加载 systemctl 配置。

      $ sudo systemctl daemon-reload
      
  2. 重新启动 Docker。

  3. 通过检查 netstat 的输出来确认 dockerd 是否正在监听配置的端口,以查看更改是否得到遵守。

    $ sudo netstat -lntp | grep dockerd
    tcp        0      0 127.0.0.1:2375          0.0.0.0:*               LISTEN      3758/dockerd
    

Docker 客户端将遵循DOCKER_HOST环境变量来为客户端设置-H标志。使用以下命令之一:

$ docker -H tcp://127.0.0.1:2375 ps

或者

$ export DOCKER_HOST="tcp://127.0.0.1:2375"
$ docker ps

答案4

对于那些在使用 Ubuntu 服务器 20.04 的环境中寻找这个答案的人来说折断

此评论 github 问题应该会给你所需的上下文。在我的例子中,我没有找到 $SNAP_DATA 环境变量集,所以我不得不在系统上查找所有 daemon.json 文件并使用带有前缀的/var文件

$ sudo find / -name daemon.json

就我而言,它有两个不相关的条目,因此我仅添加了我的条目:

{
  [.....]
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}

上述 IP 决定了从哪里可以访问它,端口可以是您想要公开的任何端口。在我的特定情况下,我无法让它与特定 IP 一起工作,而是必须使用 0.0.0.0,否则重新启动时会失败并出现以下错误:

aufs aufs_fill_super:918:mount[3724]: no arg
overlayfs: missing 'lowerdir'
aufs aufs_fill_super:918:mount[3772]: no arg
overlayfs: missing 'lowerdir'
aufs aufs_fill_super:918:mount[3820]: no arg
overlayfs: missing 'lowerdir'

奇怪的是,当使用 0.0.0.0 时,它实际上会吐出一对上述错误行,但之后它确实可以工作。对我来说,因为这是一个虚拟机,所以这对我来说是可以接受的。

相关内容