纸飞机的信笺
博客Awesome开源Demos制品库

Docker Engine API 通过 HTTP 接口来控制 Docker

  1. 端口号和测试方式
  2. Windows 系统的 Docker Desktop
  3. Linux 系统上的 Docker
  4. 各平台通用的推荐方式

Docker Engine API 通过 HTTP 接口来控制 Docker

2022年 10月 30日Docker#Docker#DevOps留言: ...

Docker Engine API 让我们可以通过 HTTP 请求来获取容器的状态、执行相关的 Docker 命令,它提供 RESTful 的 HTTP 接口,返回 JSON 格式数据,便于我们使用 Node.js 等程序进行访问。

可以参考 Docker Engine API 文档,此外,大部分编程语言都有对应的 SDK,可以在官网的 SDK 列表 找到。

端口号和测试方式#

Docker Engine API 的端口号是 2375 和 2376。通常只用前者;后者是基于 TLS 连接,需要额外配置证书。

可以使用这个指令判断 API 是否开启:

curl http://localhost:2375/version

如果 API 已经正确开启,会返回一段 JSON 数据:

{"Platform":{"Name":"Docker Engine - Community"}, ...(省略)

Windows 系统的 Docker Desktop#

Docker Desktop 的设置页面,可以直接开启 Docker Engine API(在 macOS 上没有),如下图:

开启后,需要关闭并重新打开 Docker Desktop。只点击右下角的 “Apply & restart”,或者是右键任务栏图标选择 “Restart” 可能会不生效。

Linux 系统上的 Docker#

在 Linux 上,Docker 不会默认把基于 TCP 的控制端口放开,而是要通过配置来告诉 Docker 使用哪种类型的 Socket 来监听请求。 默认情况,Docker 只在 /var/run/docker.sock 提供 unix 的 Socket,也就是我们常用的 docker 终端命令。

第一种方式: Docker 支持 unix、tcp、fd 这三种协议的通讯,我们可以修改 dockerd 的启动指令,令其开放 tcp 协议的通讯。 阅读 Docker Daemon CLI 文档 可以看到,使用 -H 参数来配置 dockerd 监听 API 请求的方式。

编辑 Docker 的服务配置文件(路径中的 lib 也可能是 etc):

sudo vim /lib/systemd/system/docker.service

可以看到,Docker 启动指令是这样的:

ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

这里的 -H fd:// 表示监听文件描述符 Socket,以实现 Docker 的服务激活功能。 我们需要添加 -H tcp://0.0.0.0:2375 来让 Docker 监听 2375 端口,但只添加这一个参数会使我们无法使用 docker 终端命令,所以再添加一个 -H unix:///var/run/docker.sock 来保持对终端指令的响应。

最终编辑为:

ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --containerd=/run/containerd/containerd.sock

然后重启 Docker:

sudo systemctl daemon-reload
sudo systemctl restart docker.service

此时便可以通过本机的 2375 端口来进行使用 API 操作 Docker 引擎了。 也可以将上面的 0.0.0.0 改为 127.0.0.1,此时只有本机的服务才能访问 API,外部传入的请求无法访问。

第二种方式: 通过文档可以得知,dockerd 的 -H 启动指令其实对应了 daemon.json 中的 hosts 配置项,所以我们可以通过 daemon.json 来配置,这样就不需要修改 dockerd 的服务配置了。

编辑 daemon.json,如果没有则先创建:

sudo vim /etc/docker/daemon.json

添加以下键值对并保存:

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

这样操作,达成的效果和第一种方法中的添加 -H 是一样。

但是,存在 一个问题 一直没有解决,那就是因为 dockerd 的服务配置默认有一个 -H fd:// 配置,在 daemon.json 中配置 hosts 会导致和启动指令冲突,而我们的目的是避免修改服务配置,所以,需要使用一种方式覆盖原始的服务配置。解决方法:

创建一个配置文件:/etc/systemd/system/docker.service.d/override.conf,这一步可能要切换成 root 用户来进行; 编辑填入以下内容:

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

然后重启 Docker 服务即可。 这种方式不用修改 dockerd 的原始服务配置。

以上的方式均不适用 macOS,因为 macOS 并不是通过 systemd 启动 docker,且 macOS 的 Docker Desktop 也没有开放 2375 端口的选项。

各平台通用的推荐方式#

这种方式适用于各个平台,且不需要更改 Docker 的任何配置,是最推荐的做法。

了解了原理,那么就存在一种思路,将 tcp 的连接转为 unix 的连接,也就是将 tcp://0.0.0.0:2375 的连接转发到 unix:///var/run/docker.sock,这样便可以实现开放 Docker Engine API 的 HTTP 访问了。

这种方法需使用名为 bobrik/socat 的镜像来启动一个容器。它的 Docker Compose 配置如下:

services:
  docker-api:
    image: bobrik/socat
    container_name: docker-api
    volumes:
      - '/var/run/docker.sock:/var/run/docker.sock'
    command: TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock
    # 将端口绑定到宿主机。如果不需要,下面两行可以注释掉
    ports:
      - '2375:2375'

这样便可以通过 2375 端口来访问 Docker Engine API 了。

从配置文件中可以看出,启动容器后提供指令,使得其中的程序将 2375 端口的 tcp 连接转发到 docker.sock;而又配置了 volumes 卷映射,将宿主机的 docker.sock 透传给容器,所以 tcp 连接被直接发送到了宿主机的 Docker 服务上。 如果需要绑定到宿主机的端口上,则可以使用 ports 端口映射。

注意,上面例子中,bobrik/socat 这个镜像版本太旧,现在可能已经无法拉取; 因此可以自己构建一个新的并使用,此处给出 Dockerfile 文件:

FROM alpine:3.1
 
RUN apk --update add socat
 
ENTRYPOINT ["socat"]

你也可以使用 chiskat/docker-api 这个镜像,它是我专门为了访问 Docker Engine API 而构建的。 它的用法和 bobrik/socat 相同,但是它额外预设好了 command 启动指令,所以你不需要在使用时再提供 command 配置了,只需要正确挂载 /var/run/docker.sock 即可通过 2375 端口访问 Docker Engine API。

修订记录

  • 2026年 5月 6日
    feat(blog): 博客支持日期、类别、标签分组;更新博客文章页面
  • 2026年 1月 14日旧版 Hexo 博客
    chore(website): 新的用户名,替换全局的 jia-niang 和 paperplanecc 为 chiskat
  • 2024年 4月 30日旧版 Hexo 博客
    feat(article): 《Docker Engine API》篇更新,提供新的镜像用法
  • 2024年 4月 24日旧版 Hexo 博客
    feat(article): 《Docker Engine API》更新
  • 2024年 4月 7日旧版 Hexo 博客
    feat(article): 《docker api》篇更新
查看全部修订

留言