远程访问 Docker Daemon

介绍

最近的项目中涉及到监控远程主机上的 Docker 容器的运行状况,即通过本地 docker 客户端访问远程主机的 docker 服务端,以此来监控远程主机上的 Docker 容器。但是 Docker Daemon 默认情况下是只允许本地访问的,不允许远程访问。本文将首先介绍 Docker Daemon 的连接方式,然后说明如何配置远程访问。


Docker Daemon 的连接方式

  1. UNIX 域套接字

    默认就是这种方式, 会生成一个 /var/run/docker.sock 文件, UNIX 域套接字用于本地进程之间的通讯, 这种方式相比于网络套接字效率更高, 但局限性就是只能被本地的客户端访问。

  2. tcp 端口监听

    服务端开启端口监听 dockerd -H IP:PORT , 客户端通过指定IP和端口访问服务端 docker -H IP:PORT 。通过这种方式, 任何人只要知道了你暴露的ip和端口就能随意访问你的docker服务了, 这是一件很危险的事, 因为docker的权限很高, 不法分子可以从这突破取得服务端宿主机的最高权限。


配置 Docker 远程访问

看到一些资料上面说可以通过修改 /etc/default/docker 文件来修改 Docker Daemon 的配置,也就是编辑docker的配置文件 /etc/default/docker 中的 DOCKER_OPTS 选项成同时监听本地 unix socket 和远程 http socket(2375)

1
DOCKER_OPTS="-H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375"

但是通过这种方法修改完成重新启动 docker 守护进程之后,Docker Daemon 并没有在监听 2375 端口。然后发现其实在 /etc/default/docker 文件也有说到:

1
2
3
4
# THIS FILE DOES NOT APPLY TO SYSTEMD
#
# Please see the documentation for "systemd drop-ins":
# https://docs.docker.com/engine/admin/systemd/

因为 Ubuntu 16.04 使用 systemd 来管理 docker 进程,/etc/default/docker 文件已经不再起作用了,该文件只对更老的系统起作用。正确的配置方式如下:


主要参考该链接:Adjustments to docker setting

1. Changes to default options

安装好 Docker 后可能有一些选项需要修改,就像我们这里想要配置 Docker Daemon 允许远程访问一样。有两种方法:

  • 修改 /etc/default/docker /lib/systemd/system/docker.service 文件,但是这种方法对不同版本的 Docker 有不同的配置方法,不推荐。
  • 创建 /etc/docker/daemon.json 来作为配置文件,Docker 推荐使用这种方法,这也是我们接下来介绍的。

注:这里使用的是 Ubuntu 16.04 LTS 系统,使用了 systemd 来管理 docker 进程。而更老版本的 Ubuntu 系统没有使用 systemd,所以只需要修改 /etc/default/docker 文件就够了。

开始之前,先关闭 docker 进程:

1
$ sudo service docker stop

注意:在上面的原文链接的方法中,还会修改 docker 的默认目录,也就是将 /var/lib/docker 修改成了 /data/docker ,修改之后我们原来的容器镜像都会找不到的,所以我们就不修改默认目录,还是使用原来的 /var/lib/docker。可以使用以下命令查看 docker 默认目录:

1
2
$ docker info | grep "Docker Root Dir"
Docker Root Dir: /var/lib/docker

2. Create/modify files

创建 /etc/docker/daemon.json 文件(如果已经存在则修改),加入以下内容:

1
2
3
{
"hosts" : ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}
  • "unix:///var/run/docker.sock":unix socket,本地客户端将通过这个来连接 Docker Daemon。
  • "tcp://0.0.0.0:2375":tcp socket,表示允许任何远程客户端通过 2375 端口连接 Docker Daemon。

注意:这里也和原文链接有点不同。

3. Servers using systemd:

可以使用 systemctl edit docker 来调用文本编辑器修改指定的单元或单元实例,ubuntu 默认调用的是 nano 编辑器,不是很好用,如果不熟悉 nano 编辑器的操作可以使用 vim 编辑器。

主要也就是新建或修改 /etc/systemd/system/docker.service.d/override.conf ,其内容如下:

1
2
3
4
##Add this to the file for the docker daemon to use different ExecStart parameters (more things can be added here)
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd

解释一下:

默认情况下使用 systemd 时,docker.service 的设置为:ExecStart=/usr/bin/dockerd -H fd:// ,这将覆盖写到 daemon.json 中的任何 hosts 。通过在 override.conf 文件中将 ExecStart 仅仅定义为:ExecStart=/usr/bin/dockerd ,这将会使用在 daemon.json 中设置的 hosts 。这个文件中的第一行ExecStart= 必须要有,因为它将用于清楚默认的 ExecStart 参数。如果是修改 docker.service 的文件而不是创建 override.conf,那么下次 systemd 重启时,docker.service 文件也会被重新创建。

重新加载 daemon 并重启 docker 服务:

1
2
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker.service

检查端口监听:

1
2
# netstat -ntlp |grep dockerd
tcp6 0 0 :::2375 :::* LISTEN 6259/dockerd

如果检查端口监听时出现下面的提示,则说明需要使用 root 权限。

1
2
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)

在远程主机上面通过 tcp socket 来访问本机的 Docker Daemon 服务:

1
2
3
$ docker -H 192.168.1.130:2375 images

$ docker -H 192.168.1.130:2375 ps

其中 192.168.1.130 是开放了远程访问的主机的 IP。

另外需要注意的是这种操作是不太安全的,仅用于测试使用。