如何通过 TCP 公开 docker API?

Lor*_*oh. 21 docker

我正在使用 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:~$
Run Code Online (Sandbox Code Playgroud)

编辑: 运行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
Run Code Online (Sandbox Code Playgroud)

Lor*_*oh. 31

感谢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:
Run Code Online (Sandbox Code Playgroud)

然后

sudo systemctl daemon-reload
sudo systemctl restart docker.service
Run Code Online (Sandbox Code Playgroud)

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

  • 切勿直接编辑 docker 服务脚本(或任何服务脚本)。SystemD 具有内置的差异编辑功能。使用`systemctl edit docker.service` 和 systemctl 将创建一个包含您编辑的新文件。这可以防止更新擦除您的更改。SystemD 将在运行时合并这两个文件。这里的好文件:https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units#editing-unit-files (12认同)
  • 在 Ubuntu Server 18.04 上,它是这样工作的:`ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:4243` (6认同)
  • 我确认此更改导致 Dockerd 在 Ubuntu 16.04 上使用 docker-ce ver 17.06 侦听 HTTP 请求。就是直接修改服务脚本感觉不对。 (2认同)

小智 9

有一个官方文档描述了如何配置 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
    
    Run Code Online (Sandbox Code Playgroud)
  3. 保存文件。

  4. 重新加载 systemctl 配置。

    $ sudo systemctl daemon-reload
    
    Run Code Online (Sandbox Code Playgroud)
  5. 重新启动 Docker。

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

    $ sudo netstat -lntp | grep dockerd
    tcp        0      0 127.0.0.1:2375          0.0.0.0:*               LISTEN      3758/dockerd
    
    Run Code Online (Sandbox Code Playgroud)

配置远程访问daemon.json

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

    {
    "hosts": ["unix:///var/run/docker.sock", "tcp://127.0.0.1:2375"]
    }
    
    Run Code Online (Sandbox Code Playgroud)

    将 Docker 配置为同时使用 systemd 单元文件和 daemon.json 文件来侦听连接会导致冲突,导致 Docker 无法启动。

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

      [Service]
      ExecStart=
      ExecStart=/usr/bin/dockerd
      
      Run Code Online (Sandbox Code Playgroud)
    2. 保存文件。

    3. 重新加载 systemctl 配置。

      $ sudo systemctl daemon-reload
      
      Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)

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

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

或者

$ export DOCKER_HOST="tcp://127.0.0.1:2375"
$ docker ps
Run Code Online (Sandbox Code Playgroud)


BMi*_*tch 8

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

该覆盖只是将所有命令行标志从 systemd 取消设置到 dockerd 守护进程。完成后,您可以覆盖 docker 使用的 /etc/docker/daemon.json 中的每个设置,并且可以根据设置重新加载,而无需重新启动守护程序。例如,这里有一个例子 /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
}
Run Code Online (Sandbox Code Playgroud)

为了您的目的,您只需要在那里设置主机。

上述配置文件的一个极其重要的部分是 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
Run Code Online (Sandbox Code Playgroud)

  • 一个很好的答案,它将在 docker 服务的未来更新中继续存在。这是正确的方法。 (2认同)

ead*_*ter 6

如果你不想重新配置并重新启动你的 docker 守护进程,你可以简单地使用ncat(从nmap包中)将 unix 套接字桥接到 TCP 套接字:

ncat -lknvp 2375 -c "ncat -U /var/run/docker.sock"
Run Code Online (Sandbox Code Playgroud)

作为替代方案,您可以使用socat 或其他工具